From: havoc Date: Sun, 22 Jun 2003 09:58:55 +0000 (+0000) Subject: This is the network rewrite I've been working on for over a week; multiplayer should... X-Git-Tag: xonotic-v0.1.0preview~6587 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=812ff6ba44c87de88a410e493b8093033867b12c;p=xonotic%2Fdarkplaces.git This is the network rewrite I've been working on for over a week; multiplayer should work through NAT routers now. A few other commits (a new clientcolors extension for example) have snuck their way into this commit because they were waiting while the cvs was down. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3093 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_demo.c b/cl_demo.c index 5f7ad080..468cdc60 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -27,8 +27,8 @@ void CL_FinishTimeDemo (void); DEMO CODE -When a demo is playing back, all NET_SendMessages are skipped, and -NET_GetMessages are read from the demo file. +When a demo is playing back, all outgoing network messages are skipped, and +incoming messages are read from the demo file. Whenever cl.time gets past the last received message, another message is read from the demo file. @@ -115,80 +115,66 @@ void CL_WriteDemoMessage (void) /* ==================== -CL_GetMessage +CL_ReadDemoMessage -Handles recording and playback of demos, on top of NET_ code +Handles playback of demos ==================== */ -int CL_GetMessage (void) +void CL_ReadDemoMessage(void) { - int r, i; - float f; + int r, i; + float f; - if (cls.demoplayback) - { - if (cls.demopaused) // LordHavoc: pausedemo - return 0; + if (!cls.demoplayback) + return; + + // LordHavoc: pausedemo + if (cls.demopaused) + return; // decide if it is time to grab the next message - if (cls.signon == SIGNONS) // always grab until fully connected + // always grab until fully connected + if (cls.signon == SIGNONS) + { + if (cls.timedemo) { - if (cls.timedemo) + if (host_framecount == cls.td_lastframe) { - if (host_framecount == cls.td_lastframe) - return 0; // already read this frame's message - cls.td_lastframe = host_framecount; + // already read this frame's message + return; + } + cls.td_lastframe = host_framecount; // if this is the second frame, grab the real td_starttime // so the bogus time on the first frame doesn't count - if (host_framecount == cls.td_startframe + 1) - cls.td_starttime = realtime; - } - else if (cl.time <= cl.mtime[0]) - { - return 0; // don't need another message yet - } - } - - // get the next message - FS_Read (cls.demofile, &net_message.cursize, 4); - VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); - for (i=0 ; i<3 ; i++) - { - r = FS_Read (cls.demofile, &f, 4); - cl.mviewangles[0][i] = LittleFloat (f); + if (host_framecount == cls.td_startframe + 1) + cls.td_starttime = realtime; } - - net_message.cursize = LittleLong (net_message.cursize); - if (net_message.cursize > MAX_DATAGRAM) - Host_Error ("Demo message > MAX_DATAGRAM"); - r = FS_Read (cls.demofile, net_message.data, net_message.cursize); - if (r != net_message.cursize) + else if (cl.time <= cl.mtime[0]) { - CL_Disconnect (); - return 0; + // don't need another message yet + return; } - - return 1; } - while (1) + // get the next message + FS_Read(cls.demofile, &net_message.cursize, 4); + net_message.cursize = LittleLong(net_message.cursize); + VectorCopy(cl.mviewangles[0], cl.mviewangles[1]); + for (i = 0;i < 3;i++) { - r = NET_GetMessage (cls.netcon); - - if (r != 1 && r != 2) - return r; - - // discard nop keepalive message - if (net_message.cursize == 1 && net_message.data[0] == svc_nop) - Con_Printf ("<-- server to client keepalive\n"); - else - break; + r = FS_Read(cls.demofile, &f, 4); + cl.mviewangles[0][i] = LittleFloat(f); } - if (cls.demorecording) - CL_WriteDemoMessage (); - - return r; + if (net_message.cursize > NET_MAXMESSAGE) + Host_Error("Demo message > NET_MAXMESSAGE"); + if (FS_Read(cls.demofile, net_message.data, net_message.cursize) == (size_t)net_message.cursize) + { + MSG_BeginReading(); + CL_ParseServerMessage(); + } + else + CL_Disconnect(); } diff --git a/cl_input.c b/cl_input.c index 018eb2c1..f92087c5 100644 --- a/cl_input.c +++ b/cl_input.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -189,12 +189,12 @@ float CL_KeyState (kbutton_t *key) { float val; qboolean impulsedown, impulseup, down; - + impulsedown = key->state & 2; impulseup = key->state & 4; down = key->state & 1; val = 0; - + if (impulsedown && !impulseup) { if (down) @@ -225,7 +225,7 @@ float CL_KeyState (kbutton_t *key) } key->state &= 1; // clear impulses - + return val; } @@ -307,14 +307,14 @@ Send the intended movement message to the server ================ */ void CL_BaseMove (usercmd_t *cmd) -{ +{ if (cls.signon != SIGNONS) return; - + CL_AdjustAngles (); - + memset (cmd, 0, sizeof(*cmd)); - + if (in_strafe.state & 1) { cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right); @@ -328,10 +328,10 @@ void CL_BaseMove (usercmd_t *cmd) cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down); if (! (in_klook.state & 1) ) - { + { cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward); cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back); - } + } // // adjust for speed key @@ -351,12 +351,12 @@ void CL_BaseMove (usercmd_t *cmd) CL_SendMove ============== */ -void CL_SendMove (usercmd_t *cmd) +void CL_SendMove(usercmd_t *cmd) { - int i; - int bits; - sizebuf_t buf; - qbyte data[128]; + int i; + int bits; + sizebuf_t buf; + qbyte data[128]; static double lastmovetime; static float forwardmove, sidemove, upmove, total; // accumulation @@ -381,10 +381,8 @@ void CL_SendMove (usercmd_t *cmd) cl.cmd = *cmd; -// -// send the movement message -// - MSG_WriteByte (&buf, clc_move); + // send the movement message + MSG_WriteByte (&buf, clc_move); MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times @@ -404,14 +402,12 @@ void CL_SendMove (usercmd_t *cmd) MSG_WriteAngle (&buf, cl.viewangles[i]); } - MSG_WriteShort (&buf, forwardmove); - MSG_WriteShort (&buf, sidemove); - MSG_WriteShort (&buf, upmove); + MSG_WriteShort (&buf, forwardmove); + MSG_WriteShort (&buf, sidemove); + MSG_WriteShort (&buf, upmove); forwardmove = sidemove = upmove = 0; -// -// send button bits -// + // send button bits bits = 0; if ( in_attack.state & 3 ) @@ -429,35 +425,31 @@ void CL_SendMove (usercmd_t *cmd) if (in_button7.state & 3) bits |= 64;in_button7.state &= ~2; if (in_button8.state & 3) bits |= 128;in_button8.state &= ~2; - MSG_WriteByte (&buf, bits); + MSG_WriteByte (&buf, bits); - MSG_WriteByte (&buf, in_impulse); + MSG_WriteByte (&buf, in_impulse); in_impulse = 0; // LordHavoc: should we ack this on receipt instead? would waste net bandwidth though i = EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase); if (i > 0) { - MSG_WriteByte (&buf, clc_ackentities); - MSG_WriteLong (&buf, i); + MSG_WriteByte(&buf, clc_ackentities); + MSG_WriteLong(&buf, i); } -// -// deliver the message -// + // deliver the message if (cls.demoplayback) return; -// -// always dump the first two messages, because they may contain leftover inputs from the last level -// + // always dump the first two messages, because they may contain leftover inputs from the last level if (++cl.movemessages <= 2) return; - if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1) + if (NetConn_SendUnreliableMessage(cls.netcon, &buf) == -1) { - Con_Printf ("CL_SendMove: lost server connection\n"); - CL_Disconnect (); + Con_Printf("CL_SendMove: lost server connection\n"); + CL_Disconnect(); } } diff --git a/cl_main.c b/cl_main.c index cdd48bad..d1b514ce 100644 --- a/cl_main.c +++ b/cl_main.c @@ -27,11 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // we need to declare some mouse variables here, because the menu system // references them even when on a unix system. -// these two are not intended to be set directly -cvar_t cl_name = {CVAR_SAVE, "_cl_name", "player"}; -cvar_t cl_color = {CVAR_SAVE, "_cl_color", "0"}; -cvar_t cl_pmodel = {CVAR_SAVE, "_cl_pmodel", "0"}; - cvar_t cl_shownet = {0, "cl_shownet","0"}; cvar_t cl_nolerp = {0, "cl_nolerp", "0"}; @@ -60,7 +55,6 @@ cvar_t cl_beams_lightatend = {CVAR_SAVE, "cl_beams_lightatend", "0"}; cvar_t cl_noplayershadow = {CVAR_SAVE, "cl_noplayershadow", "0"}; -mempool_t *cl_scores_mempool; mempool_t *cl_refdef_mempool; mempool_t *cl_entities_mempool; @@ -104,7 +98,6 @@ void CL_ClearState (void) if (!sv.active) Host_ClearMemory (); - Mem_EmptyPool(cl_scores_mempool); Mem_EmptyPool(cl_entities_mempool); // wipe the entire cl structure @@ -160,7 +153,7 @@ Sends a disconnect message to the server This is also called on Host_Error, so it shouldn't cause any errors ===================== */ -void CL_Disconnect (void) +void CL_Disconnect(void) { if (cls.state == ca_dedicated) return; @@ -177,22 +170,26 @@ void CL_Disconnect (void) cl.worldmodel = NULL; if (cls.demoplayback) - CL_StopPlayback (); - else if (cls.state == ca_connected) + CL_StopPlayback(); + else if (cls.netcon) { if (cls.demorecording) - CL_Stop_f (); - - Con_DPrintf ("Sending clc_disconnect\n"); - SZ_Clear (&cls.message); - MSG_WriteByte (&cls.message, clc_disconnect); - NET_SendUnreliableMessage (cls.netcon, &cls.message); - SZ_Clear (&cls.message); - NET_Close (cls.netcon); - cls.state = ca_disconnected; // prevent this code from executing again during Host_ShutdownServer + CL_Stop_f(); + + Con_DPrintf("Sending clc_disconnect\n"); + SZ_Clear(&cls.message); + MSG_WriteByte(&cls.message, clc_disconnect); + NetConn_SendUnreliableMessage(cls.netcon, &cls.message); + SZ_Clear(&cls.message); + NetConn_Close(cls.netcon); + cls.netcon = NULL; // if running a local server, shut it down if (sv.active) + { + // prevent this code from executing again during Host_ShutdownServer + cls.state = ca_disconnected; Host_ShutdownServer(false); + } } cls.state = ca_disconnected; @@ -214,29 +211,38 @@ void CL_Disconnect_f (void) ===================== CL_EstablishConnection -Host should be either "local" or a net address to be passed on +Host should be either "local" or a net address ===================== */ -void CL_EstablishConnection (char *host) +void CL_EstablishConnection(const char *host) { if (cls.state == ca_dedicated) return; - if (cls.demoplayback) - return; - - CL_Disconnect (); - - cls.netcon = NET_Connect (host); - if (!cls.netcon) - Host_Error ("CL_Connect: connect failed\n"); - Con_DPrintf ("CL_EstablishConnection: connected to %s\n", host); + // clear menu's connect error message + m_return_reason[0] = 0; - cls.demonum = -1; // not in the demo loop now - cls.state = ca_connected; - cls.signon = 0; // need all the signon messages before playing + // stop demo loop in case this fails + cls.demonum = -1; + CL_Disconnect(); - CL_ClearState (); + if (LHNETADDRESS_FromString(&cls.connect_address, host, 26000) && (cls.connect_mysocket = NetConn_ChooseClientSocketForAddress(&cls.connect_address))) + { + cls.connect_trying = true; + cls.connect_remainingtries = 3; + cls.connect_nextsendtime = 0; + if (sv.active) + { + NetConn_ClientFrame(); + NetConn_ServerFrame(); + NetConn_ClientFrame(); + NetConn_ServerFrame(); + NetConn_ClientFrame(); + NetConn_ServerFrame(); + NetConn_ClientFrame(); + NetConn_ServerFrame(); + } + } } /* @@ -1408,33 +1414,9 @@ CL_ReadFromServer Read all incoming data from the server =============== */ -int CL_ReadFromServer (void) +int CL_ReadFromServer(void) { - int ret, netshown; - - cl.oldtime = cl.time; - cl.time += cl.frametime; - - netshown = false; - do - { - ret = CL_GetMessage (); - if (ret == -1) - Host_Error ("CL_ReadFromServer: lost server connection"); - if (!ret) - break; - - cl.last_received_message = realtime; - - if (cl_shownet.integer) - netshown = true; - - CL_ParseServerMessage (); - } - while (ret && cls.state == ca_connected); - - if (netshown) - Con_Printf ("\n"); + CL_ReadDemoMessage(); r_refdef.numentities = 0; cl_num_entities = 0; @@ -1442,15 +1424,12 @@ int CL_ReadFromServer (void) if (cls.state == ca_connected && cls.signon == SIGNONS) { - CL_RelinkEntities (); + CL_RelinkEntities(); // run cgame code (which can add more entities) CL_CGVM_Frame(); } -// -// bring the links up to date -// return 0; } @@ -1459,76 +1438,46 @@ int CL_ReadFromServer (void) CL_SendCmd ================= */ -void CL_SendCmd (void) +void CL_SendCmd(void) { - usercmd_t cmd; - - if (cls.state != ca_connected) - return; + usercmd_t cmd; if (cls.signon == SIGNONS) { - // get basic movement from keyboard - CL_BaseMove (&cmd); + // get basic movement from keyboard + CL_BaseMove(&cmd); - IN_PreMove(); // OS independent code + // OS independent code + IN_PreMove(); - // allow mice or other external controllers to add to the move - IN_Move (&cmd); + // allow mice or other external controllers to add to the move + IN_Move(&cmd); - IN_PostMove(); // OS independent code + // OS independent code + IN_PostMove(); - // send the unreliable message - CL_SendMove (&cmd); - } - else if (cls.signon == 0 && !cls.demoplayback) - { - // LordHavoc: fix for NAT routing of netquake: - // bounce back a clc_nop message to the newly allocated server port, - // to establish a routing connection for incoming frames, - // the server waits for this before sending anything - if (realtime > cl.sendnoptime) - { - cl.sendnoptime = realtime + 3; - Con_DPrintf("sending clc_nop to get server's attention\n"); - { - sizebuf_t buf; - qbyte data[128]; - buf.maxsize = 128; - buf.cursize = 0; - buf.data = data; - MSG_WriteByte(&buf, clc_nop); - if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1) - { - Con_Printf ("CL_SendCmd: lost server connection\n"); - CL_Disconnect (); - } - } - } + // send the unreliable message + CL_SendMove(&cmd); } if (cls.demoplayback) { - SZ_Clear (&cls.message); + SZ_Clear(&cls.message); return; } -// send the reliable message - if (!cls.message.cursize) - return; // no message at all - - if (!NET_CanSendMessage (cls.netcon)) + // send the reliable message (forwarded commands) if there is one + if (cls.message.cursize && NetConn_CanSendMessage(cls.netcon)) { - Con_DPrintf ("CL_WriteToServer: can't send\n"); if (developer.integer) + { + Con_Printf("CL_SendCmd: sending reliable message:\n"); SZ_HexDumpToConsole(&cls.message); - return; + } + if (NetConn_SendReliableMessage(cls.netcon, &cls.message) == -1) + Host_Error("CL_WriteToServer: lost server connection"); + SZ_Clear(&cls.message); } - - if (NET_SendMessage (cls.netcon, &cls.message) == -1) - Host_Error ("CL_WriteToServer: lost server connection"); - - SZ_Clear (&cls.message); } // LordHavoc: pausedemo command @@ -1541,39 +1490,6 @@ static void CL_PauseDemo_f (void) Con_Printf("Demo unpaused\n"); } -/* -====================== -CL_PModel_f -LordHavoc: Intended for Nehahra, I personally think this is dumb, but Mindcrime won't listen. -====================== -*/ -static void CL_PModel_f (void) -{ - int i; - eval_t *val; - - if (Cmd_Argc () == 1) - { - Con_Printf ("\"pmodel\" is \"%s\"\n", cl_pmodel.string); - return; - } - i = atoi(Cmd_Argv(1)); - - if (cmd_source == src_command) - { - if (cl_pmodel.integer == i) - return; - Cvar_SetValue ("_cl_pmodel", i); - if (cls.state == ca_connected) - Cmd_ForwardToServer (); - return; - } - - host_client->pmodel = i; - if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel))) - val->_float = i; -} - /* ====================== CL_Fog_f @@ -1599,7 +1515,6 @@ CL_Init */ void CL_Init (void) { - cl_scores_mempool = Mem_AllocPool("client player info"); cl_entities_mempool = Mem_AllocPool("client entities"); cl_refdef_mempool = Mem_AllocPool("refdef"); @@ -1619,10 +1534,6 @@ void CL_Init (void) // // register our commands // - Cvar_RegisterVariable (&cl_name); - Cvar_RegisterVariable (&cl_color); - if (gamemode == GAME_NEHAHRA) - Cvar_RegisterVariable (&cl_pmodel); Cvar_RegisterVariable (&cl_upspeed); Cvar_RegisterVariable (&cl_forwardspeed); Cvar_RegisterVariable (&cl_backspeed); @@ -1657,8 +1568,6 @@ void CL_Init (void) // LordHavoc: added pausedemo Cmd_AddCommand ("pausedemo", CL_PauseDemo_f); - if (gamemode == GAME_NEHAHRA) - Cmd_AddCommand ("pmodel", CL_PModel_f); Cvar_RegisterVariable(&r_draweffects); Cvar_RegisterVariable(&cl_explosions); diff --git a/cl_parse.c b/cl_parse.c index 9f11a47d..160a7bb2 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -99,6 +99,8 @@ cvar_t demo_nehahra = {0, "demo_nehahra", "0"}; qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces +mempool_t *cl_scores_mempool; + /* ================== CL_ParseStartSoundPacket @@ -164,59 +166,44 @@ When the client is taking a long time to load stuff, send keepalive messages so the server doesn't disconnect. ================== */ + +static qbyte olddata[NET_MAXMESSAGE]; void CL_KeepaliveMessage (void) { - float time; + float time; static float lastmsg; - int ret; - int c; - sizebuf_t old; - qbyte olddata[8192]; - - if (sv.active) - return; // no need if server is local - if (cls.demoplayback) + int oldreadcount; + qboolean oldbadread; + sizebuf_t old; + + // no need if server is local and definitely not if this is a demo + if (sv.active || cls.demoplayback) return; // read messages from server, should just be nops + oldreadcount = msg_readcount; + oldbadread = msg_badread; old = net_message; - memcpy (olddata, net_message.data, net_message.cursize); + memcpy(olddata, net_message.data, net_message.cursize); - do - { - ret = CL_GetMessage (); - switch (ret) - { - default: - Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed"); - case 0: - break; // nothing waiting - case 1: - Host_Error ("CL_KeepaliveMessage: received a message"); - break; - case 2: - c = MSG_ReadByte(); - if (c != svc_nop) - Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop"); - break; - } - } while (ret); + NetConn_ClientFrame(); + msg_readcount = oldreadcount; + msg_badread = oldbadread; net_message = old; - memcpy (net_message.data, olddata, net_message.cursize); - -// check time - time = Sys_DoubleTime (); - if (time - lastmsg < 5) - return; - lastmsg = time; - -// write out a nop - Con_Printf ("--> client to server keepalive\n"); + memcpy(net_message.data, olddata, net_message.cursize); - MSG_WriteByte (&cls.message, clc_nop); - NET_SendMessage (cls.netcon, &cls.message); - SZ_Clear (&cls.message); + if (cls.netcon && NetConn_CanSendMessage(cls.netcon) && (time = Sys_DoubleTime()) - lastmsg >= 5) + { + lastmsg = time; + // write out a nop + Con_Printf("--> client to server keepalive\n"); + MSG_WriteByte(&cls.message, clc_nop); + NetConn_SendReliableMessage(cls.netcon, &cls.message); + SZ_Clear(&cls.message); + // try not to utterly crush the computer with work, that's just rude + Sys_Sleep(); + } } void CL_ParseEntityLump(char *entdata) @@ -359,6 +346,7 @@ void CL_ParseServerInfo (void) Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients); return; } + Mem_EmptyPool(cl_scores_mempool); cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores)); // parse gametype @@ -1376,7 +1364,7 @@ CL_ParseServerMessage ===================== */ int parsingerror = false; -void CL_ParseServerMessage (void) +void CL_ParseServerMessage(void) { int cmd; int i, entitiesupdated; @@ -1384,11 +1372,16 @@ void CL_ParseServerMessage (void) char *cmdlogname[32], *temp; int cmdindex, cmdcount = 0; + if (cls.demorecording) + CL_WriteDemoMessage (); + + cl.last_received_message = realtime; + // // if recording demos, copy the message out // if (cl_shownet.integer == 1) - Con_Printf ("%i ",net_message.cursize); + Con_Printf ("%f %i\n", realtime, net_message.cursize); else if (cl_shownet.integer == 2) Con_Printf ("------------------\n"); @@ -1396,7 +1389,7 @@ void CL_ParseServerMessage (void) // // parse the message // - MSG_BeginReading (); + //MSG_BeginReading (); entitiesupdated = false; @@ -1473,6 +1466,8 @@ void CL_ParseServerMessage (void) break; case svc_nop: + if (cls.signon < SIGNONS) + Con_Printf("<-- server to client keepalive\n"); break; case svc_time: @@ -1735,6 +1730,7 @@ void CL_Parse_DumpPacket(void) void CL_Parse_Init(void) { // LordHavoc: added demo_nehahra cvar + cl_scores_mempool = Mem_AllocPool("client player info"); Cvar_RegisterVariable (&demo_nehahra); if (gamemode == GAME_NEHAHRA) Cvar_SetValue("demo_nehahra", 1); diff --git a/cl_screen.c b/cl_screen.c index 11bf5506..8d3babe2 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -168,7 +168,7 @@ void SCR_DrawTurtle (void) if (count < 3) return; - DrawQ_Pic (0, 0, "turtle", 0, 0, 1, 1, 1, 1, 0); + DrawQ_Pic (0, 0, "gfx/turtle.lmp", 0, 0, 1, 1, 1, 1, 0); } /* @@ -185,7 +185,7 @@ void SCR_DrawNet (void) if (cls.demoplayback) return; - DrawQ_Pic (64, 0, "net", 0, 0, 1, 1, 1, 1, 0); + DrawQ_Pic (64, 0, "gfx/net.lmp", 0, 0, 1, 1, 1, 1, 0); } /* diff --git a/client.h b/client.h index 38402f6d..a7634036 100644 --- a/client.h +++ b/client.h @@ -301,12 +301,17 @@ typedef struct // LordHavoc: pausedemo qboolean demopaused; + qboolean connect_trying; + int connect_remainingtries; + double connect_nextsendtime; + lhnetsocket_t *connect_mysocket; + lhnetaddress_t connect_address; // connection information // 0 to SIGNONS int signon; - // network socket - struct qsocket_s *netcon; + // network connection + netconn_t *netcon; // writing buffer to send to server sizebuf_t message; } @@ -512,7 +517,7 @@ extern void CL_DecayLights (void); void CL_Init (void); -void CL_EstablishConnection (char *host); +void CL_EstablishConnection(const char *host); void CL_Disconnect (void); void CL_Disconnect_f (void); @@ -560,14 +565,15 @@ char *Key_KeynumToString (int keynum); // // cl_demo.c // -void CL_StopPlayback (void); -int CL_GetMessage (void); - -void CL_NextDemo (void); -void CL_Stop_f (void); -void CL_Record_f (void); -void CL_PlayDemo_f (void); -void CL_TimeDemo_f (void); +void CL_StopPlayback(void); +void CL_ReadDemoMessage(void); +void CL_WriteDemoMessage(void); + +void CL_NextDemo(void); +void CL_Stop_f(void); +void CL_Record_f(void); +void CL_PlayDemo_f(void); +void CL_TimeDemo_f(void); // // cl_parse.c diff --git a/common.c b/common.c index 875c8d37..ab20b2c5 100644 --- a/common.c +++ b/common.c @@ -832,3 +832,66 @@ int COM_StringBeginsWith(const char *s, const char *match) return false; return true; } + +// written by Elric, thanks Elric! +char *SearchInfostring(const char *infostring, const char *key) +{ + static char value [256]; + char crt_key [256]; + size_t value_ind, key_ind; + char c; + + if (*infostring++ != '\\') + return NULL; + + value_ind = 0; + for (;;) + { + key_ind = 0; + + // Get the key name + for (;;) + { + c = *infostring++; + + if (c == '\0') + return NULL; + if (c == '\\') + { + crt_key[key_ind] = '\0'; + break; + } + + crt_key[key_ind++] = c; + } + + // If it's the key we are looking for, save it in "value" + if (!strcmp(crt_key, key)) + { + for (;;) + { + c = *infostring++; + + if (c == '\0' || c == '\\') + { + value[value_ind] = '\0'; + return value; + } + + value[value_ind++] = c; + } + } + + // Else, skip the value + for (;;) + { + c = *infostring++; + + if (c == '\0') + return NULL; + if (c == '\\') + break; + } + } +} + diff --git a/common.h b/common.h index 80e7c17c..8a52aba9 100644 --- a/common.h +++ b/common.h @@ -189,5 +189,7 @@ int matchpattern(char *in, char *pattern, int caseinsensitive); stringlist_t *listdirectory(char *path); void freedirectory(stringlist_t *list); +char *SearchInfostring(const char *infostring, const char *key); + #endif diff --git a/host.c b/host.c index 93b55015..1c8a00a2 100644 --- a/host.c +++ b/host.c @@ -175,9 +175,6 @@ void Host_Error (const char *error, ...) CL_Disconnect (); cls.demonum = -1; - // unload any partially loaded models - Mod_ClearErrorModels(); - hosterror = false; longjmp (host_abortserver, 1); @@ -342,7 +339,7 @@ Sends text across to be displayed FIXME: make this just a stuffed echo? ================= */ -void SV_ClientPrintf (const char *fmt, ...) +void SV_ClientPrintf(const char *fmt, ...) { va_list argptr; char string[1024]; @@ -362,25 +359,25 @@ SV_BroadcastPrintf Sends text to all active clients ================= */ -void SV_BroadcastPrintf (const char *fmt, ...) +void SV_BroadcastPrintf(const char *fmt, ...) { va_list argptr; char string[1024]; int i; - va_start (argptr,fmt); - vsprintf (string, fmt,argptr); - va_end (argptr); + va_start(argptr,fmt); + vsprintf(string, fmt,argptr); + va_end(argptr); for (i=0 ; imessage, svc_stufftext); - MSG_WriteString (&host_client->message, string); + MSG_WriteByte(&host_client->message, svc_stufftext); + MSG_WriteString(&host_client->message, string); } /* @@ -411,50 +408,42 @@ Called when the player is getting totally kicked off the host if (crash = true), don't bother sending signofs ===================== */ -void SV_DropClient (qboolean crash) +void SV_DropClient(qboolean crash) { int saveSelf; int i; client_t *client; - Con_Printf ("Client \"%s\" dropped\n", host_client->name); + Con_Printf("Client \"%s\" dropped\n", host_client->name); - if (!crash) + // send any final messages (don't check for errors) + if (host_client->netconnection) { - // send any final messages (don't check for errors) - if (host_client->netconnection && !host_client->netconnection->disconnected) + // free the client (the body stays around) + host_client->active = false; + + if (!crash) { -#if 1 - // LordHavoc: no opportunity for resending, so reliable is silly - MSG_WriteByte (&host_client->message, svc_disconnect); - NET_SendUnreliableMessage (host_client->netconnection, &host_client->message); -#else - if (NET_CanSendMessage (host_client->netconnection)) - { - MSG_WriteByte (&host_client->message, svc_disconnect); - NET_SendMessage (host_client->netconnection, &host_client->message); - } -#endif + // LordHavoc: no opportunity for resending, so use unreliable + MSG_WriteByte(&host_client->message, svc_disconnect); + NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message); } - } -// break the net connection - NET_Close (host_client->netconnection); - host_client->netconnection = NULL; + // break the net connection + NetConn_Close(host_client->netconnection); + host_client->netconnection = NULL; -// free the client (the body stays around) - host_client->active = false; - // note: don't clear name yet - net_activeconnections--; - - if (sv.active && host_client->edict && host_client->spawned) // LordHavoc: don't call QC if server is dead (avoids recursive Host_Error in some mods when they run out of edicts) - { - // call the prog function for removing a client - // this will set the body to a dead frame, among other things - saveSelf = pr_global_struct->self; - pr_global_struct->self = EDICT_TO_PROG(host_client->edict); - PR_ExecuteProgram (pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing"); - pr_global_struct->self = saveSelf; + // LordHavoc: don't call QC if server is dead (avoids recursive + // Host_Error in some mods when they run out of edicts) + if (sv.active && host_client->edict && host_client->spawned) + { + // call the prog function for removing a client + // this will set the body to a dead frame, among other things + saveSelf = pr_global_struct->self; + pr_global_struct->self = EDICT_TO_PROG(host_client->edict); + PR_ExecuteProgram(pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing"); + pr_global_struct->self = saveSelf; + } } // now clear name (after ClientDisconnect was called) @@ -462,22 +451,22 @@ void SV_DropClient (qboolean crash) host_client->old_frags = -999999; // send notification to all clients - for (i=0, client = svs.clients ; iactive) continue; - MSG_WriteByte (&client->message, svc_updatename); - MSG_WriteByte (&client->message, host_client - svs.clients); - MSG_WriteString (&client->message, ""); - MSG_WriteByte (&client->message, svc_updatefrags); - MSG_WriteByte (&client->message, host_client - svs.clients); - MSG_WriteShort (&client->message, 0); - MSG_WriteByte (&client->message, svc_updatecolors); - MSG_WriteByte (&client->message, host_client - svs.clients); - MSG_WriteByte (&client->message, 0); + MSG_WriteByte(&client->message, svc_updatename); + MSG_WriteByte(&client->message, host_client - svs.clients); + MSG_WriteString(&client->message, ""); + MSG_WriteByte(&client->message, svc_updatefrags); + MSG_WriteByte(&client->message, host_client - svs.clients); + MSG_WriteShort(&client->message, 0); + MSG_WriteByte(&client->message, svc_updatecolors); + MSG_WriteByte(&client->message, host_client - svs.clients); + MSG_WriteByte(&client->message, 0); } - NET_Heartbeat (1); + NetConn_Heartbeat(1); } /* @@ -503,55 +492,56 @@ void Host_ShutdownServer(qboolean crash) sv.active = false; // stop all client sounds immediately - CL_Disconnect (); + CL_Disconnect(); - NET_Heartbeat (2); - NET_Heartbeat (2); + NetConn_Heartbeat(2); + NetConn_Heartbeat(2); // flush any pending messages - like the score!!! start = Sys_DoubleTime(); do { count = 0; + NetConn_ClientFrame(); + NetConn_ServerFrame(); for (i=0, host_client = svs.clients ; iactive && host_client->message.cursize) { - if (NET_CanSendMessage (host_client->netconnection)) + if (NetConn_CanSendMessage(host_client->netconnection)) { - NET_SendMessage(host_client->netconnection, &host_client->message); - SZ_Clear (&host_client->message); + NetConn_SendReliableMessage(host_client->netconnection, &host_client->message); + SZ_Clear(&host_client->message); } else - { - NET_GetMessage(host_client->netconnection); count++; - } } } if ((Sys_DoubleTime() - start) > 3.0) break; } - while (count); + while(count); // make sure all the clients know we're disconnecting buf.data = message; buf.maxsize = 4; buf.cursize = 0; MSG_WriteByte(&buf, svc_disconnect); - count = NET_SendToAll(&buf, 5); + count = NetConn_SendToAll(&buf, 5); if (count) - Con_Printf("Host_ShutdownServer: NET_SendToAll failed for %u clients\n", count); + Con_Printf("Host_ShutdownServer: NetConn_SendToAll failed for %u clients\n", count); for (i=0, host_client = svs.clients ; iactive) SV_DropClient(crash); // server shutdown + NetConn_CloseServerPorts(); + // // clear structures // - memset (&sv, 0, sizeof(sv)); - memset (svs.clients, 0, svs.maxclients * sizeof(client_t)); + memset(&sv, 0, sizeof(sv)); + memset(svs.clients, 0, svs.maxclients * sizeof(client_t)); } @@ -678,6 +668,9 @@ void Host_ServerFrame (void) // LordHavoc: cap server at sys_ticrate in listen games if (cls.state != ca_dedicated && svs.maxclients > 1 && ((realtime - lastservertime) < sys_ticrate.value)) return; + + NetConn_ServerFrame(); + // run the world state if (!sv.paused && (svs.maxclients > 1 || (key_dest == key_game && !key_consoleactive))) sv.frametime = pr_global_struct->frametime = frametimetotal; @@ -687,24 +680,21 @@ void Host_ServerFrame (void) lastservertime = realtime; // set the time and clear the general datagram - SV_ClearDatagram (); - -// check for new clients - SV_CheckForNewClients (); + SV_ClearDatagram(); // read client messages - SV_RunClients (); + SV_RunClients(); // move things around and think // always pause in single player if in console or menus if (sv.frametime) - SV_Physics (); + SV_Physics(); // send all messages to the clients - SV_SendClientMessages (); + SV_SendClientMessages(); // send an heartbeat if enough time has passed since the last one - NET_Heartbeat (0); + NetConn_Heartbeat(0); } @@ -722,37 +712,35 @@ void _Host_Frame (float time) static double time3 = 0; int pass1, pass2, pass3; - if (setjmp (host_abortserver) ) + if (setjmp(host_abortserver)) return; // something bad happened, or the server disconnected -// keep the random time dependent - rand (); + // keep the random time dependent + rand(); -// decide the simulation time - if (!Host_FilterTime (time)) + // decide the simulation time + if (!Host_FilterTime(time)) { // if time was rejected, don't totally hog the CPU Sys_Sleep(); return; } -// get new key events - Sys_SendKeyEvents (); + // get new key events + Sys_SendKeyEvents(); -// allow mice or other external controllers to add commands - IN_Commands (); + // allow mice or other external controllers to add commands + IN_Commands(); -// process console commands - Cbuf_Execute (); + // process console commands + Cbuf_Execute(); // LordHavoc: map and load are delayed until video is initialized Host_PerformSpawnServerAndLoadGame(); - NET_Poll(); - -// if running the server locally, make intentions now - if (sv.active) - CL_SendCmd (); + // if running the server locally, make intentions now + if (cls.state == ca_connected && sv.active) + CL_SendCmd(); //------------------- // @@ -760,11 +748,11 @@ void _Host_Frame (float time) // //------------------- -// check for commands typed to the host - Host_GetConsoleCommands (); + // check for commands typed to the host + Host_GetConsoleCommands(); if (sv.active) - Host_ServerFrame (); + Host_ServerFrame(); //------------------- // @@ -772,48 +760,53 @@ void _Host_Frame (float time) // //------------------- -// if running the server remotely, send intentions now after -// the incoming messages have been read - if (!sv.active) - CL_SendCmd (); + cl.oldtime = cl.time; + cl.time += cl.frametime; + + NetConn_ClientFrame(); -// fetch results from server if (cls.state == ca_connected) - CL_ReadFromServer (); + { + // if running the server remotely, send intentions now after + // the incoming messages have been read + if (!sv.active) + CL_SendCmd(); + CL_ReadFromServer(); + } ui_update(); CL_VideoFrame(); -// update video + // update video if (host_speeds.integer) - time1 = Sys_DoubleTime (); + time1 = Sys_DoubleTime(); - CL_UpdateScreen (); + CL_UpdateScreen(); if (host_speeds.integer) - time2 = Sys_DoubleTime (); + time2 = Sys_DoubleTime(); -// update audio + // update audio if (cls.signon == SIGNONS) { // LordHavoc: this used to use renderer variables (eww) vec3_t forward, right, up; AngleVectors(cl.viewangles, forward, right, up); - S_Update (cl_entities[cl.viewentity].render.origin, forward, right, up); + S_Update(cl_entities[cl.viewentity].render.origin, forward, right, up); } else - S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin); + S_Update(vec3_origin, vec3_origin, vec3_origin, vec3_origin); CDAudio_Update(); if (host_speeds.integer) { pass1 = (time1 - time3)*1000000; - time3 = Sys_DoubleTime (); + time3 = Sys_DoubleTime(); pass2 = (time2 - time1)*1000000; pass3 = (time3 - time2)*1000000; - Con_Printf ("%6ius total %6ius server %6ius gfx %6ius snd\n", + Con_Printf("%6ius total %6ius server %6ius gfx %6ius snd\n", pass1+pass2+pass3, pass1, pass2, pass3); } @@ -879,22 +872,22 @@ void Host_Init (void) developer.value = 1; } - Cmd_Init (); + Cmd_Init(); Memory_Init_Commands(); R_Modules_Init(); - Cbuf_Init (); - V_Init (); - COM_Init (); - Host_InitLocal (); - W_LoadWadFile ("gfx.wad"); - Key_Init (); - Con_Init (); - Chase_Init (); - M_Init (); - PR_Init (); - Mod_Init (); - NET_Init (); - SV_Init (); + Cbuf_Init(); + V_Init(); + COM_Init(); + Host_InitLocal(); + W_LoadWadFile("gfx.wad"); + Key_Init(); + Con_Init(); + Chase_Init(); + M_Init(); + PR_Init(); + Mod_Init(); + NetConn_Init(); + SV_Init(); Con_Printf ("Builddate: %s\n", buildstring); @@ -905,16 +898,16 @@ void Host_Init (void) VID_Init(); Render_Init(); - S_Init (); - CDAudio_Init (); - CL_Init (); + S_Init(); + CDAudio_Init(); + CL_Init(); } Cbuf_InsertText ("exec quake.rc\n"); - Cbuf_Execute (); - Cbuf_Execute (); - Cbuf_Execute (); - Cbuf_Execute (); + Cbuf_Execute(); + Cbuf_Execute(); + Cbuf_Execute(); + Cbuf_Execute(); host_initialized = true; @@ -947,7 +940,7 @@ void Host_Shutdown(void) Host_WriteConfiguration (); CDAudio_Shutdown (); - NET_Shutdown (); + NetConn_Shutdown (); S_Shutdown(); if (cls.state != ca_dedicated) diff --git a/host_cmd.c b/host_cmd.c index 98d35266..9e202d1e 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -51,7 +51,7 @@ Host_Status_f void Host_Status_f (void) { client_t *client; - int seconds, minutes, hours = 0, j; + int seconds, minutes, hours = 0, j, players; void (*print) (const char *fmt, ...); if (cmd_source == src_command) @@ -66,19 +66,18 @@ void Host_Status_f (void) else print = SV_ClientPrintf; + for (players = 0, j = 0;j < svs.maxclients;j++) + if (svs.clients[j].active) + players++; print ("host: %s\n", Cvar_VariableString ("hostname")); print ("version: %s build %s\n", gamename, buildstring); - if (tcpipAvailable) - print ("tcp/ip: %s\n", my_tcpip_address); - if (ipxAvailable) - print ("ipx: %s\n", my_ipx_address); print ("map: %s\n", sv.name); - print ("players: %i active (%i max)\n\n", net_activeconnections, svs.maxclients); + print ("players: %i active (%i max)\n\n", players, svs.maxclients); for (j=0, client = svs.clients ; jactive) continue; - seconds = (int)(net_time - client->netconnection->connecttime); + seconds = (int)(realtime - client->netconnection->connecttime); minutes = seconds / 60; if (minutes) { @@ -312,7 +311,7 @@ This is sent just before a server changes levels */ void Host_Reconnect_f (void) { - SCR_BeginLoadingPlaque (); + SCR_BeginLoadingPlaque(); cls.signon = 0; // need new connection messages } @@ -325,14 +324,7 @@ User command to connect to server */ void Host_Connect_f (void) { - char name[MAX_QPATH]; - - cls.demonum = -1; // stop demo loop in case this fails - if (cls.demoplayback) - CL_Disconnect (); - strcpy (name, Cmd_Argv(1)); - CL_EstablishConnection (name); - Host_Reconnect_f (); + CL_EstablishConnection(Cmd_Argv(1)); } @@ -543,8 +535,6 @@ void Host_PerformLoadGame(char *name) str = FS_Getline (f); sscanf (str, "%f\n",&time); - CL_Disconnect_f (); - SV_SpawnServer (mapname); if (!sv.active) { @@ -625,11 +615,9 @@ void Host_PerformLoadGame(char *name) for (i = 0;i < NUM_SPAWN_PARMS;i++) svs.clients->spawn_parms[i] = spawn_parms[i]; - if (cls.state != ca_dedicated) - { - CL_EstablishConnection ("local"); - Host_Reconnect_f (); - } + // make sure we're connected to loopback + if (cls.state == ca_disconnected || !(cls.state == ca_connected && cls.netcon != NULL && LHNETADDRESS_GetAddressType(&cls.netcon->peeraddress) == LHNETADDRESSTYPE_LOOP)) + CL_EstablishConnection("local"); } //============================================================================ @@ -639,9 +627,10 @@ void Host_PerformLoadGame(char *name) Host_Name_f ====================== */ +cvar_t cl_name = {CVAR_SAVE, "_cl_name", "player"}; void Host_Name_f (void) { - char newName[64]; + char newName[sizeof(host_client->name)]; if (Cmd_Argc () == 1) { @@ -650,10 +639,10 @@ void Host_Name_f (void) } if (Cmd_Argc () == 2) - strncpy(newName, Cmd_Argv(1), 15); + strncpy(newName, Cmd_Argv(1), sizeof(host_client->name) - 1); else - strncpy(newName, Cmd_Args(), 15); - newName[15] = 0; + strncpy(newName, Cmd_Args(), sizeof(host_client->name) - 1); + newName[sizeof(host_client->name) - 1] = 0; if (cmd_source == src_command) { @@ -669,6 +658,7 @@ void Host_Name_f (void) if (strcmp(host_client->name, newName) != 0) Con_Printf ("%s renamed to %s\n", host_client->name, newName); strcpy (host_client->name, newName); + strcpy (host_client->old_name, newName); sv_player->v->netname = PR_SetString(host_client->name); // send notification to all clients @@ -841,6 +831,7 @@ void Host_Tell_f(void) Host_Color_f ================== */ +cvar_t cl_color = {CVAR_SAVE, "_cl_color", "0"}; void Host_Color_f(void) { int top, bottom; @@ -892,7 +883,11 @@ void Host_Color_f(void) } else { + eval_t *val; + if ((val = GETEDICTFIELDVALUE(sv_player, eval_clientcolors))) + val->_float = playercolor; host_client->colors = playercolor; + host_client->old_colors = playercolor; sv_player->v->team = bottom + 1; // send notification to all clients @@ -961,6 +956,40 @@ void Host_Pause_f (void) } } +/* +====================== +Host_PModel_f +LordHavoc: only supported for Nehahra, I personally think this is dumb, but Mindcrime won't listen. +====================== +*/ +cvar_t cl_pmodel = {CVAR_SAVE, "_cl_pmodel", "0"}; +static void Host_PModel_f (void) +{ + int i; + eval_t *val; + + if (Cmd_Argc () == 1) + { + Con_Printf ("\"pmodel\" is \"%s\"\n", cl_pmodel.string); + return; + } + i = atoi(Cmd_Argv(1)); + + if (cmd_source == src_command) + { + if (cl_pmodel.integer == i) + return; + Cvar_SetValue ("_cl_pmodel", i); + if (cls.state == ca_connected) + Cmd_ForwardToServer (); + return; + } + + host_client->pmodel = i; + if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel))) + val->_float = i; +} + //=========================================================================== @@ -996,9 +1025,9 @@ Host_Spawn_f */ void Host_Spawn_f (void) { - int i; - client_t *client; - edict_t *ent; + int i; + client_t *client; + edict_t *ent; func_t RestoreGame; mfunction_t *f; @@ -1015,12 +1044,12 @@ void Host_Spawn_f (void) } // LordHavoc: moved this above the QC calls at FrikaC's request -// send all current names, colors, and frag counts + // send all current names, colors, and frag counts SZ_Clear (&host_client->message); ent = sv_player; -// run the entrance script + // run the entrance script if (sv.loadgame) { // loaded games are fully initialized already @@ -1038,22 +1067,11 @@ void Host_Spawn_f (void) } else { - eval_t *val; - // set up the edict - ED_ClearEdict(ent); - ent->v->colormap = NUM_FOR_EDICT(ent); - ent->v->team = (host_client->colors & 15) + 1; - ent->v->netname = PR_SetString(host_client->name); - if ((val = GETEDICTFIELDVALUE(ent, eval_pmodel))) - val->_float = host_client->pmodel; - // copy spawn parms out of the client_t - for (i=0 ; i< NUM_SPAWN_PARMS ; i++) (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i]; // call the spawn function - pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(sv_player); PR_ExecuteProgram (pr_global_struct->ClientConnect, "QC function ClientConnect is missing"); @@ -1065,7 +1083,7 @@ void Host_Spawn_f (void) } -// send time of update + // send time of update MSG_WriteByte (&host_client->message, svc_time); MSG_WriteFloat (&host_client->message, sv.time); @@ -1073,16 +1091,16 @@ void Host_Spawn_f (void) { MSG_WriteByte (&host_client->message, svc_updatename); MSG_WriteByte (&host_client->message, i); - MSG_WriteString (&host_client->message, client->name); + MSG_WriteString (&host_client->message, client->old_name); MSG_WriteByte (&host_client->message, svc_updatefrags); MSG_WriteByte (&host_client->message, i); MSG_WriteShort (&host_client->message, client->old_frags); MSG_WriteByte (&host_client->message, svc_updatecolors); MSG_WriteByte (&host_client->message, i); - MSG_WriteByte (&host_client->message, client->colors); + MSG_WriteByte (&host_client->message, client->old_colors); } -// send all current light styles + // send all current light styles for (i=0 ; imessage, svc_lightstyle); @@ -1090,9 +1108,7 @@ void Host_Spawn_f (void) MSG_WriteString (&host_client->message, sv.lightstyles[i]); } -// -// send some stats -// + // send some stats MSG_WriteByte (&host_client->message, svc_updatestat); MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS); MSG_WriteLong (&host_client->message, pr_global_struct->total_secrets); @@ -1109,11 +1125,11 @@ void Host_Spawn_f (void) MSG_WriteByte (&host_client->message, STAT_MONSTERS); MSG_WriteLong (&host_client->message, pr_global_struct->killed_monsters); -// send a fixangle -// Never send a roll angle, because savegames can catch the server -// in a state where it is expecting the client to correct the angle -// and it won't happen if the game was just loaded, so you wind up -// with a permanent head tilt + // send a fixangle + // Never send a roll angle, because savegames can catch the server + // in a state where it is expecting the client to correct the angle + // and it won't happen if the game was just loaded, so you wind up + // with a permanent head tilt MSG_WriteByte (&host_client->message, svc_setangle); for (i=0 ; i < 2 ; i++) MSG_WriteAngle (&host_client->message, ent->v->angles[i] ); @@ -1612,10 +1628,10 @@ void Host_PerformSpawnServerAndLoadGame(void) Host_PerformLoadGame(sv_loadgame); else if (sv_spawnmap[0]) SV_SpawnServer(sv_spawnmap); - if (sv.active && cls.state == ca_disconnected) - Cmd_ExecuteString ("connect local", src_command); sv_loadgame[0] = 0; sv_spawnmap[0] = 0; + if (sv.active && cls.state == ca_disconnected) + Cmd_ExecuteString ("connect local", src_command); } //============================================================================= @@ -1650,17 +1666,12 @@ void Host_InitCommands (void) Cmd_AddCommand ("changelevel", Host_Changelevel_f); Cmd_AddCommand ("connect", Host_Connect_f); Cmd_AddCommand ("reconnect", Host_Reconnect_f); - Cmd_AddCommand ("name", Host_Name_f); Cmd_AddCommand ("version", Host_Version_f); Cmd_AddCommand ("say", Host_Say_f); Cmd_AddCommand ("say_team", Host_Say_Team_f); Cmd_AddCommand ("tell", Host_Tell_f); - Cmd_AddCommand ("color", Host_Color_f); Cmd_AddCommand ("kill", Host_Kill_f); Cmd_AddCommand ("pause", Host_Pause_f); - Cmd_AddCommand ("spawn", Host_Spawn_f); - Cmd_AddCommand ("begin", Host_Begin_f); - Cmd_AddCommand ("prespawn", Host_PreSpawn_f); Cmd_AddCommand ("kick", Host_Kick_f); Cmd_AddCommand ("ping", Host_Ping_f); Cmd_AddCommand ("load", Host_Loadgame_f); @@ -1674,5 +1685,18 @@ void Host_InitCommands (void) Cmd_AddCommand ("viewframe", Host_Viewframe_f); Cmd_AddCommand ("viewnext", Host_Viewnext_f); Cmd_AddCommand ("viewprev", Host_Viewprev_f); + + Cvar_RegisterVariable (&cl_name); + Cmd_AddCommand ("name", Host_Name_f); + Cvar_RegisterVariable (&cl_color); + Cmd_AddCommand ("color", Host_Color_f); + if (gamemode == GAME_NEHAHRA) + { + Cvar_RegisterVariable (&cl_pmodel); + Cmd_AddCommand ("pmodel", Host_PModel_f); + } + Cmd_AddCommand ("prespawn", Host_PreSpawn_f); + Cmd_AddCommand ("spawn", Host_Spawn_f); + Cmd_AddCommand ("begin", Host_Begin_f); } diff --git a/makefile b/makefile index 8a264c6f..ff45aed2 100644 --- a/makefile +++ b/makefile @@ -55,8 +55,7 @@ SERVEROBJECTS= pr_cmds.o pr_edict.o pr_exec.o sv_light.o sv_main.o sv_move.o \ SHAREDOBJECTS= cmd.o collision.o common.o crc.o cvar.o \ filematch.o host.o host_cmd.o image.o mathlib.o matrixlib.o \ model_alias.o model_brush.o model_shared.o model_sprite.o \ - net_bsd.o net_dgrm.o net_loop.o net_main.o net_master.o \ - net_udp.o palette.o portals.o protocol.o fs.o \ + netconn.o lhnet.o palette.o portals.o protocol.o fs.o \ sys_shared.o world.o wad.o zone.o COMMONOBJECTS= $(CLIENTOBJECTS) $(SERVEROBJECTS) $(SHAREDOBJECTS) diff --git a/menu.c b/menu.c index f7744e53..18e44fed 100644 --- a/menu.c +++ b/menu.c @@ -35,7 +35,6 @@ void M_Menu_Main_f (void); void M_Menu_Save_f (void); void M_Menu_MultiPlayer_f (void); void M_Menu_Setup_f (void); - void M_Menu_Net_f (void); void M_Menu_Options_f (void); void M_Menu_Options_Effects_f (void); void M_Menu_Options_ColorControl_f (void); @@ -45,8 +44,6 @@ void M_Menu_Main_f (void); void M_Menu_Quit_f (void); void M_Menu_LanConfig_f (void); void M_Menu_GameOptions_f (void); -void M_Menu_Search_f (void); -void M_Menu_InetSearch_f (void); void M_Menu_ServerList_f (void); void M_Main_Draw (void); @@ -55,7 +52,6 @@ void M_Main_Draw (void); void M_Save_Draw (void); void M_MultiPlayer_Draw (void); void M_Setup_Draw (void); - void M_Net_Draw (void); void M_Options_Draw (void); void M_Options_Effects_Draw (void); void M_Options_ColorControl_Draw (void); @@ -65,8 +61,6 @@ void M_Main_Draw (void); void M_Quit_Draw (void); void M_LanConfig_Draw (void); void M_GameOptions_Draw (void); -void M_Search_Draw (void); -void M_InetSearch_Draw (void); void M_ServerList_Draw (void); void M_Main_Key (int key); @@ -75,7 +69,6 @@ void M_Main_Key (int key); void M_Save_Key (int key); void M_MultiPlayer_Key (int key); void M_Setup_Key (int key); - void M_Net_Key (int key); void M_Options_Key (int key); void M_Options_Effects_Key (int key); void M_Options_ColorControl_Key (int key); @@ -85,23 +78,15 @@ void M_Main_Key (int key); void M_Quit_Key (int key); void M_LanConfig_Key (int key); void M_GameOptions_Key (int key); -void M_Search_Key (int key); -void M_InetSearch_Key (int key); void M_ServerList_Key (int key); qboolean m_entersound; // play after drawing a frame, so caching // won't disrupt the sound -int m_return_state; -qboolean m_return_onerror; char m_return_reason [32]; #define StartingGame (m_multiplayer_cursor == 1) #define JoiningGame (m_multiplayer_cursor == 0) -#define IPXConfig (m_net_cursor == 0) -#define TCPIPConfig (m_net_cursor == 1) - -void M_ConfigureNetSubsystem(void); // Nehahra #define NumberOfNehahraDemos 34 @@ -151,13 +136,14 @@ nehahrademonames_t NehahraDemos[NumberOfNehahraDemos] = float menu_x, menu_y, menu_width, menu_height; -void M_DrawBackground(void) +void M_Background(int width, int height) { - menu_width = 320; - menu_height = 200; + menu_width = width; + menu_height = height; menu_x = (vid.conwidth - menu_width) * 0.5; menu_y = (vid.conheight - menu_height) * 0.5; - DrawQ_Fill(0, 0, vid.conwidth, vid.conheight, 0, 0, 0, 0.5, 0); + DrawQ_Fill(menu_x, menu_y, menu_width, menu_height, 0, 0, 0, 0.5, 0); + //DrawQ_Fill(0, 0, vid.conwidth, vid.conheight, 0, 0, 0, 0.5, 0); } /* @@ -287,21 +273,13 @@ void M_ToggleMenu_f (void) { m_entersound = true; - if (key_dest == key_menu) + if (key_dest != key_menu || m_state != m_main) + M_Menu_Main_f (); + else { - if (m_state != m_main) - { - M_Menu_Main_f (); - return; - } key_dest = key_game; m_state = m_none; - return; } - //if (key_dest == key_console) - // Con_ToggleConsole_f (); - //else - M_Menu_Main_f (); } @@ -310,6 +288,8 @@ void M_Demo_Draw (void) { int i; + M_Background(320, 200); + for (i = 0;i < NumberOfNehahraDemos;i++) M_Print (16, 16 + 8*i, NehahraDemos[i].desc); @@ -397,6 +377,8 @@ void M_Main_Draw (void) int f; cachepic_t *p; + M_Background(320, 200); + M_DrawPic (16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic ("gfx/ttl_main.lmp"); M_DrawPic ( (320-p->width)/2, 4, "gfx/ttl_main.lmp"); @@ -580,6 +562,8 @@ void M_SinglePlayer_Draw (void) { cachepic_t *p; + M_Background(320, 200); + M_DrawPic (16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic ("gfx/ttl_sgl.lmp"); @@ -730,6 +714,8 @@ void M_Load_Draw (void) int i; cachepic_t *p; + M_Background(320, 200); + p = Draw_CachePic ("gfx/p_load.lmp"); M_DrawPic ( (320-p->width)/2, 4, "gfx/p_load.lmp"); @@ -746,6 +732,8 @@ void M_Save_Draw (void) int i; cachepic_t *p; + M_Background(320, 200); + p = Draw_CachePic ("gfx/p_save.lmp"); M_DrawPic ( (320-p->width)/2, 4, "gfx/p_save.lmp"); @@ -847,6 +835,8 @@ void M_MultiPlayer_Draw (void) int f; cachepic_t *p; + M_Background(320, 200); + M_DrawPic (16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic ("gfx/p_multi.lmp"); M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi.lmp"); @@ -855,10 +845,6 @@ void M_MultiPlayer_Draw (void) f = (int)(realtime * 10)%6; M_DrawPic (54, 32 + m_multiplayer_cursor * 20, va("gfx/menudot%i.lmp", f+1)); - - if (ipxAvailable || tcpipAvailable) - return; - M_PrintWhite ((320/2) - ((27*8)/2), 168, "No Communications Available"); } @@ -887,13 +873,8 @@ void M_MultiPlayer_Key (int key) switch (m_multiplayer_cursor) { case 0: - if (ipxAvailable || tcpipAvailable) - M_Menu_Net_f (); - break; - case 1: - if (ipxAvailable || tcpipAvailable) - M_Menu_Net_f (); + M_Menu_LanConfig_f (); break; case 2: @@ -982,6 +963,8 @@ void M_Setup_Draw (void) { cachepic_t *p; + M_Background(320, 200); + M_DrawPic (16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic ("gfx/p_multi.lmp"); M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi.lmp"); @@ -1125,126 +1108,6 @@ forward: setup_bottom = 15; } -//============================================================================= -/* NET MENU */ - -int m_net_cursor; -int m_net_items; -int m_net_saveHeight; - -char *net_helpMessage [] = -{ -/* .........1.........2.... */ - " Novell network LANs ", - " or Windows 95 DOS-box. ", - " ", - "(LAN=Local Area Network)", - - " Commonly used to play ", - " over the Internet, but ", - " also used on a Local ", - " Area Network. " -}; - -void M_Menu_Net_f (void) -{ - key_dest = key_menu; - m_state = m_net; - m_entersound = true; - m_net_items = 2; - - if (m_net_cursor >= m_net_items) - m_net_cursor = 0; - m_net_cursor--; - M_Net_Key (K_DOWNARROW); -} - - -void M_Net_Draw (void) -{ - int f; - cachepic_t *p; - - M_DrawPic (16, 4, "gfx/qplaque.lmp"); - p = Draw_CachePic ("gfx/p_multi.lmp"); - M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi.lmp"); - - f = 32; - - if (ipxAvailable) - M_DrawPic (72, f, "gfx/netmen3.lmp"); - else - M_DrawPic (72, f, "gfx/dim_ipx.lmp"); - - f += 19; - if (tcpipAvailable) - M_DrawPic (72, f, "gfx/netmen4.lmp"); - else - M_DrawPic (72, f, "gfx/dim_tcp.lmp"); - - if (m_net_items == 5) // JDC, could just be removed - { - f += 19; - M_DrawPic (72, f, "gfx/netmen5.lmp"); - } - - f = (320-26*8)/2; - M_DrawTextBox (f, 134, 24, 4); - f += 8; - M_Print (f, 142, net_helpMessage[m_net_cursor*4+0]); - M_Print (f, 150, net_helpMessage[m_net_cursor*4+1]); - - f = (int)(realtime * 10)%6; - M_DrawPic (54, 32 + m_net_cursor * 20, va("gfx/menudot%i.lmp", f+1)); -} - - -void M_Net_Key (int k) -{ -again: - switch (k) - { - case K_ESCAPE: - M_Menu_MultiPlayer_f (); - break; - - case K_DOWNARROW: - S_LocalSound ("misc/menu1.wav"); - if (++m_net_cursor >= m_net_items) - m_net_cursor = 0; - break; - - case K_UPARROW: - S_LocalSound ("misc/menu1.wav"); - if (--m_net_cursor < 0) - m_net_cursor = m_net_items - 1; - break; - - case K_ENTER: - m_entersound = true; - - switch (m_net_cursor) - { - case 0: - M_Menu_LanConfig_f (); - break; - - case 1: - M_Menu_LanConfig_f (); - break; - - case 2: -// multiprotocol - break; - } - } - - if (m_net_cursor == 0 && !ipxAvailable) - goto again; - if (m_net_cursor == 1 && !tcpipAvailable) - goto again; -} - //============================================================================= /* OPTIONS MENU */ @@ -1383,6 +1246,8 @@ void M_Options_Draw (void) float y; cachepic_t *p; + M_Background(320, 240); + M_DrawPic(16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic("gfx/p_option.lmp"); M_DrawPic((320-p->width)/2, 4, "gfx/p_option.lmp"); @@ -1575,6 +1440,8 @@ void M_Options_Effects_Draw (void) float y; cachepic_t *p; + M_Background(320, 200); + M_DrawPic(16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic("gfx/p_option.lmp"); M_DrawPic((320-p->width)/2, 4, "gfx/p_option.lmp"); @@ -1747,6 +1614,8 @@ void M_Options_ColorControl_Draw (void) float x, y, c, s, t, u, v; cachepic_t *p; + M_Background(320, 256); + M_DrawPic(16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic("gfx/p_option.lmp"); M_DrawPic((320-p->width)/2, 4, "gfx/p_option.lmp"); @@ -2089,6 +1958,8 @@ void M_Keys_Draw (void) cachepic_t *p; char keystring[1024]; + M_Background(320, 200); + p = Draw_CachePic ("gfx/ttl_cstm.lmp"); M_DrawPic ( (320-p->width)/2, 4, "gfx/ttl_cstm.lmp"); @@ -2241,6 +2112,8 @@ void M_Video_Draw (void) cachepic_t *p; const char* string; + M_Background(320, 200); + M_DrawPic(16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic("gfx/vidmodes.lmp"); M_DrawPic((320-p->width)/2, 4, "gfx/vidmodes.lmp"); @@ -2378,6 +2251,7 @@ void M_Menu_Help_f (void) void M_Help_Draw (void) { + M_Background(320, 200); M_DrawPic (0, 0, va("gfx/help%i.lmp", help_page)); } @@ -2527,19 +2401,20 @@ void M_Quit_Key (int key) void M_Quit_Draw (void) { - M_DrawTextBox (56, 76, 24, 4); - M_Print (64, 84, quitMessage[msgNumber*4+0]); - M_Print (64, 92, quitMessage[msgNumber*4+1]); - M_Print (64, 100, quitMessage[msgNumber*4+2]); - M_Print (64, 108, quitMessage[msgNumber*4+3]); + M_Background(208, 48); + M_DrawTextBox(0, 0, 24, 4); + M_Print(8, 8, quitMessage[msgNumber*4+0]); + M_Print(8, 16, quitMessage[msgNumber*4+1]); + M_Print(8, 24, quitMessage[msgNumber*4+2]); + M_Print(8, 32, quitMessage[msgNumber*4+3]); } //============================================================================= /* LAN CONFIG MENU */ int lanConfig_cursor = -1; -int lanConfig_cursor_table [] = {72, 92, 112, 144}; -#define NUM_LANCONFIG_CMDS 4 +int lanConfig_cursor_table [] = {56, 76, 112}; +#define NUM_LANCONFIG_CMDS 3 int lanConfig_port; char lanConfig_portname[6]; @@ -2552,17 +2427,14 @@ void M_Menu_LanConfig_f (void) m_entersound = true; if (lanConfig_cursor == -1) { - if (JoiningGame && TCPIPConfig) - lanConfig_cursor = 2; - else + if (JoiningGame) lanConfig_cursor = 1; } - if (StartingGame && lanConfig_cursor == 2) + if (StartingGame) lanConfig_cursor = 1; - lanConfig_port = DEFAULTnet_hostport; + lanConfig_port = 26000; sprintf(lanConfig_portname, "%u", lanConfig_port); - m_return_onerror = false; m_return_reason[0] = 0; } @@ -2574,6 +2446,8 @@ void M_LanConfig_Draw (void) char *startJoin; char *protocol; + M_Background(320, 200); + M_DrawPic (16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic ("gfx/p_multi.lmp"); basex = (320-p->width)/2; @@ -2583,30 +2457,20 @@ void M_LanConfig_Draw (void) startJoin = "New Game"; else startJoin = "Join Game"; - if (IPXConfig) - protocol = "IPX"; - else - protocol = "TCP/IP"; + protocol = "TCP/IP"; M_Print (basex, 32, va ("%s - %s", startJoin, protocol)); basex += 8; - M_Print (basex, 52, "Address:"); - if (IPXConfig) - M_Print (basex+9*8, 52, my_ipx_address); - else - M_Print (basex+9*8, 52, my_tcpip_address); - M_Print (basex, lanConfig_cursor_table[0], "Port"); M_DrawTextBox (basex+8*8, lanConfig_cursor_table[0]-8, 6, 1); M_Print (basex+9*8, lanConfig_cursor_table[0], lanConfig_portname); if (JoiningGame) { - M_Print (basex, lanConfig_cursor_table[1], "Search for local games..."); - M_Print (basex, lanConfig_cursor_table[2], "Search for internet games..."); - M_Print (basex, 128, "Join game at:"); - M_DrawTextBox (basex+8, lanConfig_cursor_table[3]-8, 22, 1); - M_Print (basex+16, lanConfig_cursor_table[3], lanConfig_joinname); + M_Print (basex, lanConfig_cursor_table[1], "Search for games..."); + M_Print (basex, lanConfig_cursor_table[2]-16, "Join game at:"); + M_DrawTextBox (basex+8, lanConfig_cursor_table[2]-8, 22, 1); + M_Print (basex+16, lanConfig_cursor_table[2], lanConfig_joinname); } else { @@ -2619,8 +2483,8 @@ void M_LanConfig_Draw (void) if (lanConfig_cursor == 0) M_DrawCharacter (basex+9*8 + 8*strlen(lanConfig_portname), lanConfig_cursor_table [0], 10+((int)(realtime*4)&1)); - if (lanConfig_cursor == 3) - M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [3], 10+((int)(realtime*4)&1)); + if (lanConfig_cursor == 2) + M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [2], 10+((int)(realtime*4)&1)); if (*m_return_reason) M_PrintWhite (basex, 168, m_return_reason); @@ -2634,7 +2498,7 @@ void M_LanConfig_Key (int key) switch (key) { case K_ESCAPE: - M_Menu_Net_f (); + M_Menu_MultiPlayer_f (); break; case K_UPARROW: @@ -2657,32 +2521,23 @@ void M_LanConfig_Key (int key) m_entersound = true; - M_ConfigureNetSubsystem (); + Cbuf_AddText ("stopdemo\n"); + + Cvar_SetValue("port", lanConfig_port); - if (lanConfig_cursor == 1 || lanConfig_cursor == 2) + if (lanConfig_cursor == 1) { if (StartingGame) { M_Menu_GameOptions_f (); break; } - if (lanConfig_cursor == 1) - M_Menu_Search_f(); - else - M_Menu_InetSearch_f(); + M_Menu_ServerList_f(); break; } - if (lanConfig_cursor == 3) - { - m_return_state = m_state; - m_return_onerror = true; - key_dest = key_game; - m_state = m_none; + if (lanConfig_cursor == 2) Cbuf_AddText ( va ("connect \"%s\"\n", lanConfig_joinname) ); - break; - } - break; case K_BACKSPACE: @@ -2692,7 +2547,7 @@ void M_LanConfig_Key (int key) lanConfig_portname[strlen(lanConfig_portname)-1] = 0; } - if (lanConfig_cursor == 3) + if (lanConfig_cursor == 2) { if (strlen(lanConfig_joinname)) lanConfig_joinname[strlen(lanConfig_joinname)-1] = 0; @@ -2703,7 +2558,7 @@ void M_LanConfig_Key (int key) if (key < 32 || key > 127) break; - if (lanConfig_cursor == 3) + if (lanConfig_cursor == 2) { l = strlen(lanConfig_joinname); if (l < 21) @@ -2726,7 +2581,7 @@ void M_LanConfig_Key (int key) } } - if (StartingGame && lanConfig_cursor == 3) + if (StartingGame && lanConfig_cursor == 2) { if (key == K_UPARROW) lanConfig_cursor = 1; @@ -2735,9 +2590,7 @@ void M_LanConfig_Key (int key) } l = atoi(lanConfig_portname); - if (l > 65535) - l = lanConfig_port; - else + if (l <= 65535) lanConfig_port = l; sprintf(lanConfig_portname, "%u", lanConfig_port); } @@ -3054,6 +2907,8 @@ void M_GameOptions_Draw (void) int x; gamelevels_t *g; + M_Background(320, 200); + M_DrawPic (16, 4, "gfx/qplaque.lmp"); p = Draw_CachePic ("gfx/p_multi.lmp"); M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi.lmp"); @@ -3299,7 +3154,7 @@ void M_GameOptions_Key (int key) switch (key) { case K_ESCAPE: - M_Menu_Net_f (); + M_Menu_MultiPlayer_f (); break; case K_UPARROW: @@ -3336,7 +3191,6 @@ void M_GameOptions_Key (int key) { if (sv.active) Cbuf_AddText ("disconnect\n"); - Cbuf_AddText ("listen 0\n"); // so host_netport will be re-examined Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) ); g = lookupgameinfo(); @@ -3349,97 +3203,10 @@ void M_GameOptions_Key (int key) } } -//============================================================================= -/* SEARCH MENU */ - -qboolean searchComplete = false; -double searchCompleteTime; - -void M_Menu_Search_f (void) -{ - key_dest = key_menu; - m_state = m_search; - m_entersound = false; - slistSilent = true; - slistLocal = false; - searchComplete = false; - NET_Slist_f(); - -} - - -void M_Search_Draw (void) -{ - cachepic_t *p; - int x; - - p = Draw_CachePic ("gfx/p_multi.lmp"); - M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi.lmp"); - x = (320/2) - ((12*8)/2) + 4; - M_DrawTextBox (x-8, 32, 12, 1); - M_Print (x, 40, "Searching..."); - - if(slistInProgress) - { - NET_Poll(); - return; - } - - if (! searchComplete) - { - searchComplete = true; - searchCompleteTime = realtime; - } - - if (hostCacheCount) - { - M_Menu_ServerList_f (); - return; - } - - M_PrintWhite ((320/2) - ((22*8)/2), 64, va("No %s servers found", gamename)); - if ((realtime - searchCompleteTime) < 3.0) - return; - - M_Menu_LanConfig_f (); -} - - -void M_Search_Key (int key) -{ -} - -//============================================================================= -/* INTERNET SEARCH MENU */ - -void M_Menu_InetSearch_f (void) -{ - key_dest = key_menu; - m_state = m_search; - m_entersound = false; - slistSilent = true; - slistLocal = false; - searchComplete = false; - NET_InetSlist_f(); - -} - - -void M_InetSearch_Draw (void) -{ - M_Search_Draw (); // it's the same one, so why bother? -} - - -void M_InetSearch_Key (int key) -{ -} - //============================================================================= /* SLIST MENU */ -int slist_cursor; -qboolean slist_sorted; +int slist_cursor; void M_Menu_ServerList_f (void) { @@ -3447,68 +3214,53 @@ void M_Menu_ServerList_f (void) m_state = m_slist; m_entersound = true; slist_cursor = 0; - m_return_onerror = false; m_return_reason[0] = 0; - slist_sorted = false; + Net_Slist_f(); } void M_ServerList_Draw (void) { - int n; - char string [64]; - cachepic_t *p; + int n, y, visible, start, end; + cachepic_t *p; - if (!slist_sorted) - { - if (hostCacheCount > 1) - { - int i,j; - hostcache_t temp; - for (i = 0; i < hostCacheCount; i++) - for (j = i+1; j < hostCacheCount; j++) - if (strcmp(hostcache[j].name, hostcache[i].name) < 0) - { - memcpy(&temp, &hostcache[j], sizeof(hostcache_t)); - memcpy(&hostcache[j], &hostcache[i], sizeof(hostcache_t)); - memcpy(&hostcache[i], &temp, sizeof(hostcache_t)); - } - } - slist_sorted = true; - } + // use as much vertical space as available + M_Background(640, vid.conheight); + // scroll the list as the cursor moves + visible = (vid.conheight - 16 - 32) / 8; + start = bound(0, slist_cursor - (visible >> 1), hostCacheCount - visible); + end = min(start + visible, hostCacheCount); - p = Draw_CachePic ("gfx/p_multi.lmp"); - M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi.lmp"); - for (n = 0; n < hostCacheCount; n++) + p = Draw_CachePic("gfx/p_multi.lmp"); + M_DrawPic((640 - p->width) / 2, 4, "gfx/p_multi.lmp"); + y = 32; + for (n = start;n < end;n++) { - if (hostcache[n].maxusers) - sprintf(string, "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers); - else - sprintf(string, "%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map); - M_Print (16, 32 + 8*n, string); + M_Print(0, y, hostcache[n].line1);y += 8; + M_Print(0, y, hostcache[n].line2);y += 8; } - M_DrawCharacter (0, 32 + slist_cursor*8, 12+((int)(realtime*4)&1)); + M_DrawCharacter(0, 32 + (slist_cursor - start) * 16, 12+((int)(realtime*4)&1)); if (*m_return_reason) - M_PrintWhite (16, 168, m_return_reason); + M_PrintWhite(16, vid.conheight - 8, m_return_reason); } -void M_ServerList_Key (int k) +void M_ServerList_Key(int k) { switch (k) { case K_ESCAPE: - M_Menu_LanConfig_f (); + M_Menu_LanConfig_f(); break; case K_SPACE: - M_Menu_Search_f (); + Net_Slist_f(); break; case K_UPARROW: case K_LEFTARROW: - S_LocalSound ("misc/menu1.wav"); + S_LocalSound("misc/menu1.wav"); slist_cursor--; if (slist_cursor < 0) slist_cursor = hostCacheCount - 1; @@ -3516,20 +3268,15 @@ void M_ServerList_Key (int k) case K_DOWNARROW: case K_RIGHTARROW: - S_LocalSound ("misc/menu1.wav"); + S_LocalSound("misc/menu1.wav"); slist_cursor++; if (slist_cursor >= hostCacheCount) slist_cursor = 0; break; case K_ENTER: - S_LocalSound ("misc/menu2.wav"); - m_return_state = m_state; - m_return_onerror = true; - slist_sorted = false; - key_dest = key_game; - m_state = m_none; - Cbuf_AddText ( va ("connect \"%s\"\n", hostcache[slist_cursor].cname) ); + S_LocalSound("misc/menu2.wav"); + Cbuf_AddText(va("connect \"%s\"\n", hostcache[slist_cursor].cname)); break; default: @@ -3605,11 +3352,11 @@ void M_Init (void) void M_Draw (void) { - if (m_state == m_none || key_dest != key_menu) + if (key_dest != key_menu) + m_state = m_none; + if (m_state == m_none) return; - M_DrawBackground(); - switch (m_state) { case m_none: @@ -3643,10 +3390,6 @@ void M_Draw (void) M_Setup_Draw (); break; - case m_net: - M_Net_Draw (); - break; - case m_options: M_Options_Draw (); break; @@ -3683,10 +3426,6 @@ void M_Draw (void) M_GameOptions_Draw (); break; - case m_search: - M_Search_Draw (); - break; - case m_slist: M_ServerList_Draw (); break; @@ -3737,10 +3476,6 @@ void M_Keydown (int key) M_Setup_Key (key); return; - case m_net: - M_Net_Key (key); - return; - case m_options: M_Options_Key (key); return; @@ -3777,24 +3512,9 @@ void M_Keydown (int key) M_GameOptions_Key (key); return; - case m_search: - M_Search_Key (key); - break; - case m_slist: M_ServerList_Key (key); return; } } - -void M_ConfigureNetSubsystem(void) -{ -// enable/disable net systems to match desired config - - Cbuf_AddText ("stopdemo\n"); - - if (IPXConfig || TCPIPConfig) - net_hostport = lanConfig_port; -} - diff --git a/menu.h b/menu.h index 2031fb17..e45af43d 100644 --- a/menu.h +++ b/menu.h @@ -21,13 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef MENU_H #define MENU_H -// -// the net drivers should just set the apropriate bits in m_activenet, -// instead of having the menu code look through their internal tables -// -#define MNET_IPX 1 -#define MNET_TCP 2 - enum m_state_e { m_none, m_main, @@ -37,7 +30,6 @@ enum m_state_e { m_save, m_multiplayer, m_setup, - m_net, m_options, m_video, m_keys, @@ -45,16 +37,12 @@ enum m_state_e { m_quit, m_lanconfig, m_gameoptions, - m_search, m_slist, m_options_effects, m_options_colorcontrol }; -extern int m_activenet; -extern int m_return_state; extern enum m_state_e m_state; -extern qboolean m_return_onerror; extern char m_return_reason[32]; // diff --git a/model_shared.c b/model_shared.c index fcc3a252..5703e611 100644 --- a/model_shared.c +++ b/model_shared.c @@ -242,11 +242,10 @@ static model_t *Mod_LoadModel (model_t *mod, qboolean crash, qboolean checkdisk, // LordHavoc: unload the existing model in this slot (if there is one) Mod_UnloadModel(mod); mod->isworldmodel = isworldmodel; - mod->needload = false; mod->used = true; mod->crc = crc; - // errors can prevent the corresponding mod->error = false; - mod->error = true; + // errors can prevent the corresponding mod->needload = false; + mod->needload = true; // all models use memory, so allocate a memory pool mod->mempool = Mem_AllocPool(mod->name); @@ -266,7 +265,7 @@ static model_t *Mod_LoadModel (model_t *mod, qboolean crash, qboolean checkdisk, Mem_Free(buf); // no errors occurred - mod->error = false; + mod->needload = false; return mod; } @@ -295,16 +294,6 @@ void Mod_ClearAll (void) { } -void Mod_ClearErrorModels (void) -{ - int i; - model_t *mod; - - for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++) - if (mod->error) - Mod_FreeModel(mod); -} - void Mod_ClearUsed(void) { int i; diff --git a/model_shared.h b/model_shared.h index 6bec208f..dd09ee69 100644 --- a/model_shared.h +++ b/model_shared.h @@ -102,8 +102,6 @@ typedef struct model_s qboolean isworldmodel; // true if this model is a HalfLife .bsp file qboolean ishlbsp; - // true if this model was not successfully loaded and should be purged - qboolean error; // mod_brush, mod_alias, mod_sprite modtype_t type; @@ -295,7 +293,6 @@ extern cvar_t r_fullbrights; void Mod_Init (void); void Mod_CheckLoaded (model_t *mod); void Mod_ClearAll (void); -void Mod_ClearErrorModels (void); model_t *Mod_FindName (const char *name); model_t *Mod_ForName (const char *name, qboolean crash, qboolean checkdisk, qboolean isworldmodel); void Mod_TouchModel (const char *name); diff --git a/net.h b/net.h deleted file mode 100644 index 4a69b872..00000000 --- a/net.h +++ /dev/null @@ -1,341 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net.h -- quake's interface to the networking layer - -#ifndef NET_H -#define NET_H - -struct qsockaddr -{ - short sa_family; - unsigned char sa_data[14]; -}; - - -#define NET_NAMELEN 64 - -#define NET_MAXMESSAGE (MAX_DATAGRAM + 64) -#define NET_HEADERSIZE (2 * sizeof(unsigned int)) -#define NET_DATAGRAMSIZE (MAX_DATAGRAM + NET_HEADERSIZE) - -// NetHeader flags -#define NETFLAG_LENGTH_MASK 0x0000ffff -#define NETFLAG_DATA 0x00010000 -#define NETFLAG_ACK 0x00020000 -#define NETFLAG_NAK 0x00040000 -#define NETFLAG_EOM 0x00080000 -#define NETFLAG_UNRELIABLE 0x00100000 -#define NETFLAG_CTL 0x80000000 - - -#define NET_PROTOCOL_VERSION 3 - -// This is the network info/connection protocol. It is used to find Quake -// servers, get info about them, and connect to them. Once connected, the -// Quake game protocol (documented elsewhere) is used. -// -// -// General notes: -// game_name is currently always "QUAKE", but is there so this same protocol -// can be used for future games as well; can you say Quake2? -// -// CCREQ_CONNECT -// string game_name "QUAKE" -// byte net_protocol_version NET_PROTOCOL_VERSION -// -// CCREQ_SERVER_INFO -// string game_name "QUAKE" -// byte net_protocol_version NET_PROTOCOL_VERSION -// -// CCREQ_PLAYER_INFO -// byte player_number -// -// CCREQ_RULE_INFO -// string rule -// -// -// -// CCREP_ACCEPT -// long port -// -// CCREP_REJECT -// string reason -// -// CCREP_SERVER_INFO -// string server_address -// string host_name -// string level_name -// byte current_players -// byte max_players -// byte protocol_version NET_PROTOCOL_VERSION -// -// CCREP_PLAYER_INFO -// byte player_number -// string name -// long colors -// long frags -// long connect_time -// string address -// -// CCREP_RULE_INFO -// string rule -// string value - -// note: -// There are two address forms used above. The short form is just a -// port number. The address that goes along with the port is defined as -// "whatever address you receive this reponse from". This lets us use -// the host OS to solve the problem of multiple host addresses (possibly -// with no routing between them); the host will use the right address -// when we reply to the inbound connection request. The long from is -// a full address and port in a string. It is used for returning the -// address of a server that is not running locally. - -#define CCREQ_CONNECT 0x01 -#define CCREQ_SERVER_INFO 0x02 -#define CCREQ_PLAYER_INFO 0x03 -#define CCREQ_RULE_INFO 0x04 - -#define CCREP_ACCEPT 0x81 -#define CCREP_REJECT 0x82 -#define CCREP_SERVER_INFO 0x83 -#define CCREP_PLAYER_INFO 0x84 -#define CCREP_RULE_INFO 0x85 - -typedef struct qsocket_s -{ - struct qsocket_s *next; - double connecttime; - double lastMessageTime; - double lastSendTime; - - qboolean disconnected; - qboolean canSend; - qboolean sendNext; - - int driver; - int landriver; - int socket; - void *driverdata; - - unsigned int ackSequence; - unsigned int sendSequence; - unsigned int unreliableSendSequence; - int sendMessageLength; - qbyte sendMessage [NET_MAXMESSAGE]; - - unsigned int receiveSequence; - unsigned int unreliableReceiveSequence; - int receiveMessageLength; - qbyte receiveMessage [NET_MAXMESSAGE]; - - struct qsockaddr addr; - char address[NET_NAMELEN]; -} qsocket_t; - -extern qsocket_t *net_activeSockets; -extern mempool_t *net_mempool; - -typedef struct -{ - char *name; - qboolean initialized; - int controlSock; - int (*Init) (void); - void (*Shutdown) (void); - void (*Listen) (qboolean state); - int (*OpenSocket) (int port); - int (*CloseSocket) (int socket); - int (*Connect) (int socket, struct qsockaddr *addr); - int (*CheckNewConnections) (void); - int (*Recv) (qbyte *buf, int len, struct qsockaddr *addr); - int (*Send) (qbyte *buf, int len, struct qsockaddr *addr); - int (*Read) (int socket, qbyte *buf, int len, struct qsockaddr *addr); - int (*Write) (int socket, qbyte *buf, int len, struct qsockaddr *addr); - int (*Broadcast) (int socket, qbyte *buf, int len); - char * (*AddrToString) (const struct qsockaddr *addr); - int (*StringToAddr) (const char *string, struct qsockaddr *addr); - int (*GetSocketAddr) (int socket, struct qsockaddr *addr); - int (*GetNameFromAddr) (const struct qsockaddr *addr, char *name); - int (*GetAddrFromName) (const char *name, struct qsockaddr *addr); - int (*AddrCompare) (const struct qsockaddr *addr1, const struct qsockaddr *addr2); - int (*GetSocketPort) (struct qsockaddr *addr); - int (*SetSocketPort) (struct qsockaddr *addr, int port); -} net_landriver_t; - -#define MAX_NET_DRIVERS 8 -extern int net_numlandrivers; -extern net_landriver_t net_landrivers[MAX_NET_DRIVERS]; - -typedef struct -{ - char *name; - qboolean initialized; - int (*Init) (void); - void (*Listen) (qboolean state); - void (*SearchForHosts) (qboolean xmit); - qboolean (*SearchForInetHosts) (const char *master); - qsocket_t *(*Connect) (const char *host); - qsocket_t *(*CheckNewConnections) (void); - int (*QGetMessage) (qsocket_t *sock); - int (*QSendMessage) (qsocket_t *sock, sizebuf_t *data); - int (*SendUnreliableMessage) (qsocket_t *sock, sizebuf_t *data); - qboolean (*CanSendMessage) (qsocket_t *sock); - qboolean (*CanSendUnreliableMessage) (qsocket_t *sock); - void (*Close) (qsocket_t *sock); - void (*Shutdown) (void); - void (*Heartbeat) (const char *host); - int controlSock; -} net_driver_t; - -extern int net_numdrivers; -extern net_driver_t net_drivers[MAX_NET_DRIVERS]; - -extern int DEFAULTnet_hostport; -extern int net_hostport; - -extern int net_driverlevel; -extern cvar_t hostname; -extern cvar_t developer_networking; -extern char playername[]; -extern int playercolor; - -extern int messagesSent; -extern int messagesReceived; -extern int unreliableMessagesSent; -extern int unreliableMessagesReceived; - -qsocket_t *NET_NewQSocket (void); -void NET_FreeQSocket(qsocket_t *); -double SetNetTime(void); - - -#define HOSTCACHESIZE 128 - -typedef struct -{ - char name[64]; - char map[64]; - char cname[64]; - int users; - int maxusers; - //int driver; - //int ldriver; - //struct qsockaddr addr; -} hostcache_t; - -extern int hostCacheCount; -extern hostcache_t hostcache[HOSTCACHESIZE]; - -#if !defined(_WIN32 ) && !defined (__linux__) && !defined (__sun__) -#ifndef htonl -extern unsigned long htonl (unsigned long hostlong); -#endif -#ifndef htons -extern unsigned short htons (unsigned short hostshort); -#endif -#ifndef ntohl -extern unsigned long ntohl (unsigned long netlong); -#endif -#ifndef ntohs -extern unsigned short ntohs (unsigned short netshort); -#endif -#endif - -//============================================================================ -// -// public network functions -// -//============================================================================ - -extern double net_time; -extern sizebuf_t net_message; -extern int net_activeconnections; - -void NET_Init (void); -void NET_Shutdown (void); - -struct qsocket_s *NET_CheckNewConnections (void); -// returns a new connection number if there is one pending, else -1 - -struct qsocket_s *NET_Connect (char *host); -// called by client to connect to a host. Returns -1 if not able to - -void NET_Heartbeat (int priority); -// Send an heartbeat to the master server(s). priority: 0 = lowest, 1 = state change, 2 = force - -qboolean NET_CanSendMessage (qsocket_t *sock); -// Returns true or false if the given qsocket can currently accept a -// message to be transmitted. - -int NET_GetMessage (struct qsocket_s *sock); -// returns data in net_message sizebuf -// returns 0 if no data is waiting -// returns 1 if a message was received -// returns 2 if an unreliable message was received -// returns -1 if the connection died - -int NET_SendMessage (struct qsocket_s *sock, sizebuf_t *data); -int NET_SendUnreliableMessage (struct qsocket_s *sock, sizebuf_t *data); -// returns 0 if the message connot be delivered reliably, but the connection -// is still considered valid -// returns 1 if the message was sent properly -// returns -1 if the connection died - -int NET_SendToAll(sizebuf_t *data, int blocktime); -// This is a reliable *blocking* send to all attached clients. - - -void NET_Close (struct qsocket_s *sock); -// if a dead connection is returned by a get or send function, this function -// should be called when it is convenient - -// Server calls when a client is kicked off for a game related misbehavior -// like an illegal protocal conversation. Client calls when disconnecting -// from a server. -// A netcon_t number will not be reused until this function is called for it - -void NET_Poll(void); - - -typedef struct _PollProcedure -{ - struct _PollProcedure *next; - double nextTime; - void (*procedure)(); - void *arg; -} PollProcedure; - -void SchedulePollProcedure(PollProcedure *pp, double timeOffset); - -extern qboolean ipxAvailable; -extern qboolean tcpipAvailable; -extern char my_ipx_address[NET_NAMELEN]; -extern char my_tcpip_address[NET_NAMELEN]; - -extern qboolean slistInProgress; -extern qboolean slistSilent; -extern qboolean slistLocal; - -void NET_Slist_f (void); -void NET_InetSlist_f (void); - -#endif - diff --git a/net_bsd.c b/net_bsd.c deleted file mode 100644 index 9b547d83..00000000 --- a/net_bsd.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" - -#include "net_loop.h" -#include "net_dgrm.h" - -net_driver_t net_drivers[MAX_NET_DRIVERS] = -{ - { - "Loopback", - false, - Loop_Init, - Loop_Listen, - Loop_SearchForHosts, - Loop_SearchForInetHosts, - Loop_Connect, - Loop_CheckNewConnections, - Loop_GetMessage, - Loop_SendMessage, - Loop_SendUnreliableMessage, - Loop_CanSendMessage, - Loop_CanSendUnreliableMessage, - Loop_Close, - Loop_Shutdown, - Loop_Heartbeat - } - , - { - "Datagram", - false, - Datagram_Init, - Datagram_Listen, - Datagram_SearchForHosts, - Datagram_SearchForInetHosts, - Datagram_Connect, - Datagram_CheckNewConnections, - Datagram_GetMessage, - Datagram_SendMessage, - Datagram_SendUnreliableMessage, - Datagram_CanSendMessage, - Datagram_CanSendUnreliableMessage, - Datagram_Close, - Datagram_Shutdown, - Datagram_Heartbeat - } -}; - -int net_numdrivers = 2; - -#include "net_udp.h" - -net_landriver_t net_landrivers[MAX_NET_DRIVERS] = -{ - { - "UDP", - false, - 0, - UDP_Init, - UDP_Shutdown, - UDP_Listen, - UDP_OpenSocket, - UDP_CloseSocket, - UDP_Connect, - UDP_CheckNewConnections, - UDP_Recv, - UDP_Send, - UDP_Read, - UDP_Write, - UDP_Broadcast, - UDP_AddrToString, - UDP_StringToAddr, - UDP_GetSocketAddr, - UDP_GetNameFromAddr, - UDP_GetAddrFromName, - UDP_AddrCompare, - UDP_GetSocketPort, - UDP_SetSocketPort - } -}; - -int net_numlandrivers = 1; - diff --git a/net_dgrm.c b/net_dgrm.c deleted file mode 100644 index 53ab0bda..00000000 --- a/net_dgrm.c +++ /dev/null @@ -1,1504 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_dgrm.c - -// This is enables a simple IP banning mechanism -#define BAN_TEST - -#ifdef BAN_TEST -#if defined(_WIN32) -#include -#elif defined (NeXT) -#include -#include -#else -#define AF_INET 2 /* internet */ -struct in_addr -{ - union - { - struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b; - struct { unsigned short s_w1,s_w2; } S_un_w; - unsigned long S_addr; - } S_un; -}; -#define s_addr S_un.S_addr /* can be used for most tcp & ip code */ -struct sockaddr_in -{ - short sin_family; - unsigned short sin_port; - struct in_addr sin_addr; - char sin_zero[8]; -}; -char *inet_ntoa(struct in_addr in); -unsigned long inet_addr(const char *cp); -#endif -#endif // BAN_TEST - -#include "quakedef.h" -#include "net_dgrm.h" -#include "net_master.h" - -cvar_t cl_port = {CVAR_SAVE, "cl_port", "0"}; - -// these two macros are to make the code more readable -#define sfunc net_landrivers[sock->landriver] -#define dfunc net_landrivers[net_landriverlevel] - -static int net_landriverlevel; - -/* statistic counters */ -int packetsSent = 0; -int packetsReSent = 0; -int packetsReceived = 0; -int receivedDuplicateCount = 0; -int shortPacketCount = 0; -int droppedDatagrams; - -static int myDriverLevel; - -struct -{ - unsigned int length; - unsigned int sequence; - qbyte data[MAX_DATAGRAM]; -} packetBuffer; - -/* -#ifdef DEBUG -char *StrAddr (struct qsockaddr *addr) -{ - static char buf[34]; - qbyte *p = (qbyte *)addr; - int n; - - for (n = 0; n < 16; n++) - sprintf (buf + n * 2, "%02x", *p++); - return buf; -} -#endif -*/ - - -#ifdef BAN_TEST -unsigned long banAddr = 0x00000000; -unsigned long banMask = 0xffffffff; - -void NET_Ban_f (void) -{ - char addrStr [32]; - char maskStr [32]; - void (*print) (const char *fmt, ...); - - if (cmd_source == src_command) - { - if (!sv.active) - { - Cmd_ForwardToServer (); - return; - } - print = Con_Printf; - } - else - { - if (pr_global_struct->deathmatch) - return; - print = SV_ClientPrintf; - } - - switch (Cmd_Argc ()) - { - case 1: - if (((struct in_addr *)&banAddr)->s_addr) - { - strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr)); - strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask)); - print("Banning %s [%s]\n", addrStr, maskStr); - } - else - print("Banning not active\n"); - break; - - case 2: - if (strcasecmp(Cmd_Argv(1), "off") == 0) - banAddr = 0x00000000; - else - banAddr = inet_addr(Cmd_Argv(1)); - banMask = 0xffffffff; - break; - - case 3: - banAddr = inet_addr(Cmd_Argv(1)); - banMask = inet_addr(Cmd_Argv(2)); - break; - - default: - print("BAN ip_address [mask]\n"); - break; - } -} -#endif - - -int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) -{ - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; - -#ifdef DEBUG - if (data->cursize == 0) - Sys_Error("Datagram_SendMessage: zero length message\n"); - - if (data->cursize > NET_MAXMESSAGE) - Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize); - - if (sock->canSend == false) - Sys_Error("SendMessage: called with canSend == false\n"); -#endif - - memcpy(sock->sendMessage, data->data, data->cursize); - sock->sendMessageLength = data->cursize; - - if (data->cursize <= MAX_DATAGRAM) - { - dataLen = data->cursize; - eom = NETFLAG_EOM; - } - else - { - dataLen = MAX_DATAGRAM; - eom = 0; - } - packetLen = NET_HEADERSIZE + dataLen; - - packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong(sock->sendSequence++); - memcpy (packetBuffer.data, sock->sendMessage, dataLen); - - sock->canSend = false; - - if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - sock->lastSendTime = net_time; - packetsSent++; - return 1; -} - - -int SendMessageNext (qsocket_t *sock) -{ - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; - - if (sock->sendMessageLength <= MAX_DATAGRAM) - { - dataLen = sock->sendMessageLength; - eom = NETFLAG_EOM; - } - else - { - dataLen = MAX_DATAGRAM; - eom = 0; - } - packetLen = NET_HEADERSIZE + dataLen; - - packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong(sock->sendSequence++); - memcpy (packetBuffer.data, sock->sendMessage, dataLen); - - sock->sendNext = false; - - if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - sock->lastSendTime = net_time; - packetsSent++; - return 1; -} - - -int ReSendMessage (qsocket_t *sock) -{ - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; - - if (sock->sendMessageLength <= MAX_DATAGRAM) - { - dataLen = sock->sendMessageLength; - eom = NETFLAG_EOM; - } - else - { - dataLen = MAX_DATAGRAM; - eom = 0; - } - packetLen = NET_HEADERSIZE + dataLen; - - packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong(sock->sendSequence - 1); - memcpy (packetBuffer.data, sock->sendMessage, dataLen); - - sock->sendNext = false; - - if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - sock->lastSendTime = net_time; - packetsReSent++; - return 1; -} - - -qboolean Datagram_CanSendMessage (qsocket_t *sock) -{ - if (sock->sendNext) - SendMessageNext (sock); - - return sock->canSend; -} - - -qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock) -{ - return true; -} - - -int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) -{ - int packetLen; - -#ifdef DEBUG - if (data->cursize == 0) - Sys_Error("Datagram_SendUnreliableMessage: zero length message\n"); - - if (data->cursize > MAX_DATAGRAM) - Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize); -#endif - - packetLen = NET_HEADERSIZE + data->cursize; - - packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE); - packetBuffer.sequence = BigLong(sock->unreliableSendSequence++); - memcpy (packetBuffer.data, data->data, data->cursize); - - if (sfunc.Write (sock->socket, (qbyte *)&packetBuffer, packetLen, &sock->addr) == -1) - return -1; - - packetsSent++; - return 1; -} - - -int Datagram_GetMessage (qsocket_t *sock) -{ - unsigned int length; - unsigned int flags; - int ret = 0; - struct qsockaddr readaddr; - unsigned int sequence; - unsigned int count; - int temp; - - if (!sock->canSend) - if ((net_time - sock->lastSendTime) > 1.0) - ReSendMessage (sock); - - while(1) - { - length = sfunc.Read (sock->socket, (qbyte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr); - - if (length == 0) - break; - - if ((int)length == -1) - { - Con_Printf("Read error\n"); - return -1; - } - - if ((temp = sfunc.AddrCompare(&readaddr, &sock->addr)) != 0) - { - char tempaddress1[64], tempaddress2[64]; - if (temp == 1) - { - if (developer_networking.integer) - { - dfunc.GetNameFromAddr (&sock->addr, tempaddress1); - dfunc.GetNameFromAddr (&readaddr, tempaddress2); - Con_Printf("Packet from wrong port received but accepted (Expected: %s Received: %s)\n", tempaddress1, tempaddress2); - } - } - else - { - dfunc.GetNameFromAddr (&sock->addr, tempaddress1); - dfunc.GetNameFromAddr (&readaddr, tempaddress2); - Con_Printf("Forged packet received (Expected: %s Received: %s)\n", tempaddress1, tempaddress2); - continue; - } - } - - if (length < NET_HEADERSIZE) - { - shortPacketCount++; - continue; - } - - length = BigLong(packetBuffer.length); - flags = length & (~NETFLAG_LENGTH_MASK); - length &= NETFLAG_LENGTH_MASK; - - if (flags & NETFLAG_CTL) - continue; - - sequence = BigLong(packetBuffer.sequence); - packetsReceived++; - - if (flags & NETFLAG_UNRELIABLE) - { - if (sequence < sock->unreliableReceiveSequence) - { - Con_DPrintf("Got a stale datagram\n"); - ret = 0; - break; - } - if (sequence != sock->unreliableReceiveSequence) - { - count = sequence - sock->unreliableReceiveSequence; - droppedDatagrams += count; - Con_DPrintf("Dropped %u datagram(s)\n", count); - } - sock->unreliableReceiveSequence = sequence + 1; - - length -= NET_HEADERSIZE; - - SZ_Clear (&net_message); - SZ_Write (&net_message, packetBuffer.data, length); - - ret = 2; - break; - } - - if (flags & NETFLAG_ACK) - { - if (sequence != (sock->sendSequence - 1)) - { - Con_DPrintf("Stale ACK received\n"); - continue; - } - if (sequence == sock->ackSequence) - { - sock->ackSequence++; - if (sock->ackSequence != sock->sendSequence) - Con_DPrintf("ack sequencing error\n"); - } - else - { - Con_DPrintf("Duplicate ACK received\n"); - continue; - } - sock->sendMessageLength -= MAX_DATAGRAM; - if (sock->sendMessageLength > 0) - { - memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength); - sock->sendNext = true; - } - else - { - sock->sendMessageLength = 0; - sock->canSend = true; - } - continue; - } - - if (flags & NETFLAG_DATA) - { - packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK); - packetBuffer.sequence = BigLong(sequence); - sfunc.Write (sock->socket, (qbyte *)&packetBuffer, NET_HEADERSIZE, &readaddr); - - if (sequence != sock->receiveSequence) - { - receivedDuplicateCount++; - continue; - } - sock->receiveSequence++; - - length -= NET_HEADERSIZE; - - if (flags & NETFLAG_EOM) - { - SZ_Clear(&net_message); - SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength); - SZ_Write(&net_message, packetBuffer.data, length); - sock->receiveMessageLength = 0; - - ret = 1; - break; - } - - memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length); - sock->receiveMessageLength += length; - continue; - } - } - - if (sock->sendNext) - SendMessageNext (sock); - - return ret; -} - - -void PrintStats(qsocket_t *s) -{ - Con_Printf("canSend = %4u \n", s->canSend); - Con_Printf("sendSeq = %4u ", s->sendSequence); - Con_Printf("recvSeq = %4u \n", s->receiveSequence); - Con_Printf("\n"); -} - -void NET_Stats_f (void) -{ - qsocket_t *s; - - if (Cmd_Argc () == 1) - { - Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent); - Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived); - Con_Printf("reliable messages sent = %i\n", messagesSent); - Con_Printf("reliable messages received = %i\n", messagesReceived); - Con_Printf("packetsSent = %i\n", packetsSent); - Con_Printf("packetsReSent = %i\n", packetsReSent); - Con_Printf("packetsReceived = %i\n", packetsReceived); - Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount); - Con_Printf("shortPacketCount = %i\n", shortPacketCount); - Con_Printf("droppedDatagrams = %i\n", droppedDatagrams); - } - else if (strcmp(Cmd_Argv(1), "*") == 0) - { - for (s = net_activeSockets; s; s = s->next) - PrintStats(s); - } - else - { - for (s = net_activeSockets; s; s = s->next) - if (strcasecmp(Cmd_Argv(1), s->address) == 0) - break; - if (s == NULL) - return; - PrintStats(s); - } -} - -/* -static qboolean testInProgress = false; -static int testPollCount; -static int testDriver; -static int testSocket; - -static void Test_Poll(void); -PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll}; - -static void Test_Poll(void) -{ - struct qsockaddr clientaddr; - int control; - int len; - char name[32]; - char address[64]; - int colors; - int frags; - int connectTime; - qbyte playerNumber; - int c; - - net_landriverlevel = testDriver; - - while (1) - { - len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr); - if (len < (int)sizeof(int)) - break; - - net_message.cursize = len; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - break; - if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL) - break; - if ((control & NETFLAG_LENGTH_MASK) != len) - break; - - c = MSG_ReadByte(); - if (c != CCREP_PLAYER_INFO) - Sys_Error("Unexpected repsonse to Player Info request\n"); - - playerNumber = MSG_ReadByte(); - strcpy(name, MSG_ReadString()); - colors = MSG_ReadLong(); - frags = MSG_ReadLong(); - connectTime = MSG_ReadLong(); - strcpy(address, MSG_ReadString()); - - Con_Printf("%s\n frags:%3i colors:%u %u time:%u\n %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address); - } - - testPollCount--; - if (testPollCount) - { - SchedulePollProcedure(&testPollProcedure, 0.1); - } - else - { - dfunc.CloseSocket(testSocket); - testInProgress = false; - } -} - -static void Test_f (void) -{ - const char *host; - int n, max = MAX_SCOREBOARD; - struct qsockaddr sendaddr; - - if (testInProgress) - return; - - host = Cmd_Argv (1); - - if (host && hostCacheCount) - { - for (n = 0; n < hostCacheCount; n++) - if (strcasecmp (host, hostcache[n].name) == 0) - { - if (hostcache[n].driver != myDriverLevel) - continue; - net_landriverlevel = hostcache[n].ldriver; - max = hostcache[n].maxusers; - memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); - break; - } - if (n < hostCacheCount) - goto JustDoIt; - } - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - { - if (!net_landrivers[net_landriverlevel].initialized) - continue; - - // see if we can resolve the host name - if (dfunc.GetAddrFromName(host, &sendaddr) != -1) - break; - } - if (net_landriverlevel == net_numlandrivers) - return; - -JustDoIt: - testSocket = dfunc.OpenSocket(0); - if (testSocket == -1) - return; - - testInProgress = true; - testPollCount = 20; - testDriver = net_landriverlevel; - - for (n = 0; n < max; n++) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO); - MSG_WriteByte(&net_message, n); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr); - } - SZ_Clear(&net_message); - SchedulePollProcedure(&testPollProcedure, 0.1); -} - - -static qboolean test2InProgress = false; -static int test2Driver; -static int test2Socket; - -static void Test2_Poll(void); -PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll}; - -static void Test2_Poll(void) -{ - struct qsockaddr clientaddr; - int control; - int len; - int c; - char name[256]; - char value[256]; - - net_landriverlevel = test2Driver; - name[0] = 0; - - len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr); - if (len < (int)sizeof(int)) - goto Reschedule; - - net_message.cursize = len; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - goto Error; - if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL) - goto Error; - if ((control & NETFLAG_LENGTH_MASK) != len) - goto Error; - - c = MSG_ReadByte(); - if (c != CCREP_RULE_INFO) - goto Error; - - strcpy(name, MSG_ReadString()); - if (name[0] == 0) - goto Done; - strcpy(value, MSG_ReadString()); - - Con_Printf("%-16.16s %-16.16s\n", name, value); - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_RULE_INFO); - MSG_WriteString(&net_message, name); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - -Reschedule: - SchedulePollProcedure(&test2PollProcedure, 0.05); - return; - -Error: - Con_Printf("Unexpected repsonse to Rule Info request\n"); -Done: - dfunc.CloseSocket(test2Socket); - test2InProgress = false; - return; -} - -static void Test2_f (void) -{ - const char *host; - int n; - struct qsockaddr sendaddr; - - if (test2InProgress) - return; - - host = Cmd_Argv (1); - - if (host && hostCacheCount) - { - for (n = 0; n < hostCacheCount; n++) - if (strcasecmp (host, hostcache[n].name) == 0) - { - if (hostcache[n].driver != myDriverLevel) - continue; - net_landriverlevel = hostcache[n].ldriver; - memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); - break; - } - if (n < hostCacheCount) - goto JustDoIt; - } - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - { - if (!net_landrivers[net_landriverlevel].initialized) - continue; - - // see if we can resolve the host name - if (dfunc.GetAddrFromName(host, &sendaddr) != -1) - break; - } - if (net_landriverlevel == net_numlandrivers) - return; - -JustDoIt: - test2Socket = dfunc.OpenSocket(0); - if (test2Socket == -1) - return; - - test2InProgress = true; - test2Driver = net_landriverlevel; - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_RULE_INFO); - MSG_WriteString(&net_message, ""); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr); - SZ_Clear(&net_message); - SchedulePollProcedure(&test2PollProcedure, 0.05); -} -*/ - -int Datagram_Init (void) -{ - int i; - int csock; - - myDriverLevel = net_driverlevel; - Cmd_AddCommand ("net_stats", NET_Stats_f); - Cvar_RegisterVariable (&cl_port); - - if (COM_CheckParm("-nolan")) - return -1; - - for (i = 0; i < net_numlandrivers; i++) - { - csock = net_landrivers[i].Init (); - if (csock == -1) - continue; - net_landrivers[i].initialized = true; - net_landrivers[i].controlSock = csock; - } - -#ifdef BAN_TEST - Cmd_AddCommand ("ban", NET_Ban_f); -#endif - //Cmd_AddCommand ("test", Test_f); - //Cmd_AddCommand ("test2", Test2_f); - - return 0; -} - - -void Datagram_Shutdown (void) -{ - int i; - -// -// shutdown the lan drivers -// - for (i = 0; i < net_numlandrivers; i++) - { - if (net_landrivers[i].initialized) - { - net_landrivers[i].Shutdown (); - net_landrivers[i].initialized = false; - } - } -} - - -void Datagram_Close (qsocket_t *sock) -{ - sfunc.CloseSocket(sock->socket); -} - - -void Datagram_Listen (qboolean state) -{ - int i; - - for (i = 0; i < net_numlandrivers; i++) - if (net_landrivers[i].initialized) - net_landrivers[i].Listen (state); -} - - -static qsocket_t *_Datagram_CheckNewConnections (void) -{ - struct qsockaddr clientaddr; - struct qsockaddr newaddr; - int newsock; - int acceptsock; - qsocket_t *sock; - qsocket_t *s; - int len; - int command; - int control; - int ret; - int c; - - acceptsock = dfunc.CheckNewConnections(); - if (acceptsock == -1) - return NULL; - - SZ_Clear(&net_message); - - len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr); - if (len < (int)sizeof(int)) - return NULL; - net_message.cursize = len; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - - // Messages starting by 0xFFFFFFFF are master server messages - if ((unsigned int)control == 0xFFFFFFFF) - { - int responsesize = Master_HandleMessage(); - if (responsesize > 0) - { - dfunc.Write(acceptsock, net_message.data, responsesize, &clientaddr); - SZ_Clear(&net_message); - } - return NULL; - } - if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL) - return NULL; - if ((control & NETFLAG_LENGTH_MASK) != len) - return NULL; - - command = MSG_ReadByte(); - if (command == CCREQ_SERVER_INFO) - { - if (strcmp(MSG_ReadString(), "QUAKE") != 0) - return NULL; - - Con_DPrintf("Datagram_CheckNewConnections: received CCREQ_SERVERINFO, replying.\n"); - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_SERVER_INFO); - dfunc.GetSocketAddr(acceptsock, &newaddr); - MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); - MSG_WriteString(&net_message, hostname.string); - MSG_WriteString(&net_message, sv.name); - MSG_WriteByte(&net_message, net_activeconnections); - MSG_WriteByte(&net_message, svs.maxclients); - MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - - if (command == CCREQ_PLAYER_INFO) - { - int playerNumber; - int activeNumber; - int clientNumber; - client_t *client; - - playerNumber = MSG_ReadByte(); - activeNumber = -1; - for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) - { - if (client->active) - { - activeNumber++; - if (activeNumber == playerNumber) - break; - } - } - if (clientNumber == svs.maxclients) - return NULL; - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_PLAYER_INFO); - MSG_WriteByte(&net_message, playerNumber); - MSG_WriteString(&net_message, client->name); - MSG_WriteLong(&net_message, client->colors); - MSG_WriteLong(&net_message, (int)client->edict->v->frags); - MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime)); - MSG_WriteString(&net_message, client->netconnection->address); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - - return NULL; - } - - if (command == CCREQ_RULE_INFO) - { - char *prevCvarName; - cvar_t *var; - - // find the search start location - prevCvarName = MSG_ReadString(); - var = Cvar_FindVarAfter(prevCvarName, CVAR_NOTIFY); - - // send the response - - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_RULE_INFO); - if (var) - { - MSG_WriteString(&net_message, var->name); - MSG_WriteString(&net_message, var->string); - } - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - - return NULL; - } - - if (command != CCREQ_CONNECT) - return NULL; - - if (strcmp(MSG_ReadString(), "QUAKE") != 0) - return NULL; - - c = MSG_ReadByte(); - if (c != NET_PROTOCOL_VERSION) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_REJECT); - MSG_WriteString(&net_message, "Incompatible version.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - -#ifdef BAN_TEST - // check for a ban - if (clientaddr.sa_family == AF_INET) - { - unsigned long testAddr; - testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr; - if ((testAddr & banMask) == banAddr) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_REJECT); - MSG_WriteString(&net_message, "You have been banned.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - } -#endif - - // see if this guy is already connected - for (s = net_activeSockets; s; s = s->next) - { - if (s->driver != net_driverlevel) - continue; - ret = dfunc.AddrCompare(&clientaddr, &s->addr); - if (ret >= 0) - { - // is this a duplicate connection request? - if (ret == 0 && net_time - s->connecttime < 2.0) - { - // yes, so send a duplicate reply - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_ACCEPT); - dfunc.GetSocketAddr(s->socket, &newaddr); - MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - // LordHavoc: send from s->socket instead of acceptsock, this - // way routers usually identify the connection correctly - // (thanks to faded for provoking me to recite a lengthy - // explanation of NAT nightmares, and realize this easy - // workaround for quake) - dfunc.Write (s->socket, net_message.data, net_message.cursize, &clientaddr); - // LordHavoc: also send from acceptsock, for good measure - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - // it's somebody coming back in from a crash/disconnect - // so close the old qsocket and let their retry get them back in - NET_Close(s); - return NULL; - } - } - - // allocate a QSocket - sock = NET_NewQSocket (); - if (sock == NULL) - { - // no room; try to let him know - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_REJECT); - MSG_WriteString(&net_message, "Server is full.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - return NULL; - } - - // allocate a network socket - newsock = dfunc.OpenSocket(0); - if (newsock == -1) - { - NET_FreeQSocket(sock); - return NULL; - } - - // connect to the client - if (dfunc.Connect (newsock, &clientaddr) == -1) - { - dfunc.CloseSocket(newsock); - NET_FreeQSocket(sock); - return NULL; - } - - // everything is allocated, just fill in the details - sock->socket = newsock; - sock->landriver = net_landriverlevel; - sock->addr = clientaddr; - strcpy(sock->address, dfunc.AddrToString(&clientaddr)); - - // send him back the info about the server connection he has been allocated - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREP_ACCEPT); - dfunc.GetSocketAddr(newsock, &newaddr); - MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - // LordHavoc: send from sock->socket instead of acceptsock, this way routers - // usually identify the connection correctly (thanks to faded for provoking - // me to recite a lengthy explanation of NAT nightmares, and realize this - // easy workaround for quake) - dfunc.Write (sock->socket, net_message.data, net_message.cursize, &clientaddr); - // LordHavoc: also send from acceptsock, for good measure - dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); - SZ_Clear(&net_message); - - return sock; -} - -qsocket_t *Datagram_CheckNewConnections (void) -{ - qsocket_t *ret = NULL; - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - if (net_landrivers[net_landriverlevel].initialized) - if ((ret = _Datagram_CheckNewConnections ()) != NULL) - break; - return ret; -} - - -static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr) -{ - //struct qsockaddr myaddr; - int control; - int c, n; - char cname[256]; - - if (net_message.cursize < (int)sizeof(int)) - return false; - - // don't answer our own query - //dfunc.GetSocketAddr (dfunc.controlSock, &myaddr); - //if (dfunc.AddrCompare(readaddr, &myaddr) >= 0) - // return false; - - // is the cache full? - if (hostCacheCount == HOSTCACHESIZE) - return false; - - MSG_BeginReading (); - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - return false; - if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL) - return false; - if ((control & NETFLAG_LENGTH_MASK) != net_message.cursize) - return false; - - c = MSG_ReadByte(); - if (c != CCREP_SERVER_INFO) - return false; - - // LordHavoc: because the UDP driver reports 0.0.0.0:26000 as the address - // string we just ignore it and keep the real address - MSG_ReadString(); - // hostcache only uses text addresses - strcpy(cname, dfunc.AddrToString(readaddr)); - // search the cache for this server - for (n = 0; n < hostCacheCount; n++) - //if (dfunc.AddrCompare(readaddr, &hostcache[n].addr) == 0) - if (!strcmp(cname, hostcache[n].cname)) - return false; - - // add it - hostCacheCount++; - strcpy(hostcache[n].name, MSG_ReadString()); - strcpy(hostcache[n].map, MSG_ReadString()); - hostcache[n].users = MSG_ReadByte(); - hostcache[n].maxusers = MSG_ReadByte(); - c = MSG_ReadByte(); - if (c != NET_PROTOCOL_VERSION) - { - strncpy(hostcache[n].cname, hostcache[n].name, sizeof(hostcache[n].cname) - 1); - hostcache[n].cname[sizeof(hostcache[n].cname) - 1] = 0; - strcpy(hostcache[n].name, "*"); - strncat(hostcache[n].name, hostcache[n].cname, sizeof(hostcache[n].name) - 1); - hostcache[n].name[sizeof(hostcache[n].name) - 1] = 0; - } - strcpy(hostcache[n].cname, cname); - //memcpy(&hostcache[n].addr, readaddr, sizeof(struct qsockaddr)); - //hostcache[n].driver = net_driverlevel; - //hostcache[n].ldriver = net_landriverlevel; - - /* - // check for a name conflict - for (i = 0; i < hostCacheCount; i++) - { - if (i == n) - continue; - if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0) - { - i = strlen(hostcache[n].name); - if (i < 15 && hostcache[n].name[i-1] > '8') - { - hostcache[n].name[i] = '0'; - hostcache[n].name[i+1] = 0; - } - else - hostcache[n].name[i-1]++; - i = -1; - } - } - */ - - return true; -} - - -static void _Datagram_SearchForHosts (qboolean xmit) -{ - int ret; - struct qsockaddr readaddr; - - if (xmit) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_SERVER_INFO); - MSG_WriteString(&net_message, "QUAKE"); - MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize); - SZ_Clear(&net_message); - } - - while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0) - { - net_message.cursize = ret; - Datagram_HandleServerInfo (&readaddr); - } -} - -void Datagram_SearchForHosts (qboolean xmit) -{ - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - { - if (hostCacheCount == HOSTCACHESIZE) - break; - if (net_landrivers[net_landriverlevel].initialized) - _Datagram_SearchForHosts (xmit); - } -} - - -static qboolean _Datagram_SearchForInetHosts (const char *master) -{ - qboolean result = false; - struct qsockaddr masteraddr; - struct qsockaddr readaddr; - int ret; - - if (master) - { - if (dfunc.GetAddrFromName(master, &masteraddr) != -1) - { - int portnum = 0; - const char* port = strrchr (master, ':'); - if (port) - portnum = atoi (port + 1); - if (!portnum) - portnum = MASTER_PORT; - Con_DPrintf("Datagram_SearchForInetHosts: sending %d byte message to master %s port %i\n", net_message.cursize, master, portnum); - dfunc.SetSocketPort (&masteraddr, portnum); - dfunc.Write (dfunc.controlSock, net_message.data, net_message.cursize, &masteraddr); - } - } - - while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0) - { - net_message.cursize = ret; - Con_DPrintf("Datagram_SearchForInetHosts: Read received %d byte message\n", net_message.cursize); - if (Datagram_HandleServerInfo (&readaddr)) - result = true; - else - Master_ParseServerList (&dfunc); - } - - return result; -} - - -qboolean Datagram_SearchForInetHosts (const char *master) -{ - qboolean result = false; - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - { - if (hostCacheCount == HOSTCACHESIZE) - break; - if (net_landrivers[net_landriverlevel].initialized) - if (_Datagram_SearchForInetHosts (master)) - result = true; - } - - return result; -} - - -static qsocket_t *_Datagram_Connect (const char *host) -{ - struct qsockaddr sendaddr; - struct qsockaddr readaddr; - qsocket_t *sock; - int newsock; - int ret; - int reps; - double start_time; - int control; - char *reason; - - // see if we can resolve the host name - if (dfunc.GetAddrFromName(host, &sendaddr) == -1) - return NULL; - - newsock = dfunc.OpenSocket (cl_port.integer); - if (newsock == -1) - return NULL; - - sock = NET_NewQSocket (); - if (sock == NULL) - goto ErrorReturn2; - sock->socket = newsock; - sock->landriver = net_landriverlevel; - - // connect to the host - if (dfunc.Connect (newsock, &sendaddr) == -1) - goto ErrorReturn; - - // send the connection request - Con_Printf("trying...\n");CL_UpdateScreen();CL_UpdateScreen(); - start_time = net_time; - - for (reps = 0; reps < 3; reps++) - { - SZ_Clear(&net_message); - // save space for the header, filled in later - MSG_WriteLong(&net_message, 0); - MSG_WriteByte(&net_message, CCREQ_CONNECT); - MSG_WriteString(&net_message, "QUAKE"); - MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr); - SZ_Clear(&net_message); - do - { - ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr); - // if we got something, validate it - if (ret > 0) - { - // is it from the right place? - // we don't care if the port matches (this adds support for - // the NAT fix in the server inspired by faded) - if (sfunc.AddrCompare(&readaddr, &sendaddr) < 0) - { - char tempaddress1[64], tempaddress2[64]; - dfunc.GetNameFromAddr (&sendaddr, tempaddress1); - dfunc.GetNameFromAddr (&readaddr, tempaddress2); - Con_Printf("wrong reply address (Expected: %s Received: %s)\n", tempaddress1, tempaddress2); - CL_UpdateScreen (); - CL_UpdateScreen (); - ret = 0; - continue; - } - - if (ret < (int)sizeof(int)) - { - ret = 0; - continue; - } - - net_message.cursize = ret; - MSG_BeginReading (); - - control = BigLong(*((int *)net_message.data)); - MSG_ReadLong(); - if (control == -1) - { - ret = 0; - continue; - } - if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL) - { - ret = 0; - continue; - } - if ((control & NETFLAG_LENGTH_MASK) != ret) - { - ret = 0; - continue; - } - } - } - while (ret == 0 && (SetNetTime() - start_time) < 2.5); - if (ret) - break; - Con_Printf("still trying...\n");CL_UpdateScreen();CL_UpdateScreen(); - start_time = SetNetTime(); - } - - if (ret == 0) - { - reason = "No Response"; - Con_Printf("%s\n", reason); - strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - if (ret == -1) - { - reason = "Network Error"; - Con_Printf("%s\n", reason); - strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - ret = MSG_ReadByte(); - if (ret == CCREP_REJECT) - { - reason = MSG_ReadString(); - Con_Printf("%s", reason); - strncpy(m_return_reason, reason, 31); - goto ErrorReturn; - } - - if (ret == CCREP_ACCEPT) - { - memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr)); - dfunc.SetSocketPort (&sock->addr, MSG_ReadLong()); - } - else - { - reason = "Bad Response"; - Con_Printf("%s\n", reason); - strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - dfunc.GetNameFromAddr (&sendaddr, sock->address); - - Con_Printf ("Connection accepted to %s\n", sock->address); - sock->lastMessageTime = SetNetTime(); - - // switch the connection to the specified address - if (dfunc.Connect (newsock, &sock->addr) == -1) - { - reason = "Connect to Game failed"; - Con_Printf("%s\n", reason); - strcpy(m_return_reason, reason); - goto ErrorReturn; - } - - m_return_onerror = false; - return sock; - -ErrorReturn: - NET_FreeQSocket(sock); -ErrorReturn2: - dfunc.CloseSocket(newsock); - if (m_return_onerror) - { - key_dest = key_menu; - m_state = m_return_state; - m_return_onerror = false; - } - return NULL; -} - -qsocket_t *Datagram_Connect (const char *host) -{ - qsocket_t *ret = NULL; - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - if (net_landrivers[net_landriverlevel].initialized) - if ((ret = _Datagram_Connect (host)) != NULL) - break; - return ret; -} - -static void _Datagram_Heartbeat (const char *master) -{ - struct qsockaddr masteraddr; - int portnum; - const char* port; - - if (dfunc.GetAddrFromName(master, &masteraddr) == -1) - return; - - portnum = 0; - port = strrchr (master, ':'); - if (port) - portnum = atoi (port + 1); - if (!portnum) - portnum = MASTER_PORT; - dfunc.SetSocketPort (&masteraddr, portnum); - - // FIXME: this is the only use of UDP_Send in the entire engine, add a dfunc.acceptSock to get rid of this function! - dfunc.Send (net_message.data, net_message.cursize, &masteraddr); -} - -void Datagram_Heartbeat (const char *master) -{ - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) - if (net_landrivers[net_landriverlevel].initialized) - _Datagram_Heartbeat (master); -} diff --git a/net_dgrm.h b/net_dgrm.h deleted file mode 100644 index ad2bf556..00000000 --- a/net_dgrm.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_dgrm.h - -#ifndef NET_DGRM_H -#define NET_DGRM_H - -int Datagram_Init (void); -void Datagram_Listen (qboolean state); -void Datagram_SearchForHosts (qboolean xmit); -qboolean Datagram_SearchForInetHosts (const char *master); -qsocket_t *Datagram_Connect (const char *host); -qsocket_t *Datagram_CheckNewConnections (void); -int Datagram_GetMessage (qsocket_t *sock); -int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data); -int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); -qboolean Datagram_CanSendMessage (qsocket_t *sock); -qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock); -void Datagram_Close (qsocket_t *sock); -void Datagram_Shutdown (void); -void Datagram_Heartbeat (const char *master); - -#endif - diff --git a/net_loop.c b/net_loop.c deleted file mode 100644 index 72d35700..00000000 --- a/net_loop.c +++ /dev/null @@ -1,258 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_loop.c - -#include "quakedef.h" -#include "net_loop.h" - -qboolean localconnectpending = false; -qsocket_t *loop_client = NULL; -qsocket_t *loop_server = NULL; - -int Loop_Init (void) -{ - if (cls.state == ca_dedicated) - return -1; - return 0; -} - - -void Loop_Shutdown (void) -{ -} - - -void Loop_Heartbeat (const char *master) -{ -} - - -void Loop_Listen (qboolean state) -{ -} - - -void Loop_SearchForHosts (qboolean xmit) -{ - if (!sv.active) - return; - - hostCacheCount = 1; - if (strcmp(hostname.string, "UNNAMED") == 0) - strcpy(hostcache[0].name, "local"); - else - strcpy(hostcache[0].name, hostname.string); - strcpy(hostcache[0].map, sv.name); - hostcache[0].users = net_activeconnections; - hostcache[0].maxusers = svs.maxclients; - //hostcache[0].driver = net_driverlevel; - strcpy(hostcache[0].cname, "local"); -} - - -qboolean Loop_SearchForInetHosts (const char *master) -{ - return false; -} - - -qsocket_t *Loop_Connect (const char *host) -{ - if (strcmp(host,"local") != 0) - return NULL; - - localconnectpending = true; - - if (!loop_client) - { - if ((loop_client = NET_NewQSocket ()) == NULL) - { - Con_Printf("Loop_Connect: no qsocket available\n"); - return NULL; - } - strcpy (loop_client->address, "localhost"); - } - loop_client->receiveMessageLength = 0; - loop_client->sendMessageLength = 0; - loop_client->canSend = true; - - if (!loop_server) - { - if ((loop_server = NET_NewQSocket ()) == NULL) - { - Con_Printf("Loop_Connect: no qsocket available\n"); - return NULL; - } - strcpy (loop_server->address, "LOCAL"); - } - loop_server->receiveMessageLength = 0; - loop_server->sendMessageLength = 0; - loop_server->canSend = true; - - loop_client->driverdata = (void *)loop_server; - loop_server->driverdata = (void *)loop_client; - - return loop_client; -} - - -qsocket_t *Loop_CheckNewConnections (void) -{ - if (!localconnectpending) - return NULL; - - localconnectpending = false; - loop_server->sendMessageLength = 0; - loop_server->receiveMessageLength = 0; - loop_server->canSend = true; - loop_client->sendMessageLength = 0; - loop_client->receiveMessageLength = 0; - loop_client->canSend = true; - return loop_server; -} - - -static int IntAlign(int value) -{ - return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1)); -} - - -int Loop_GetMessage (qsocket_t *sock) -{ - int ret; - int length; - - if (sock->receiveMessageLength == 0) - return 0; - - ret = sock->receiveMessage[0]; - length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8); - // alignment byte skipped here - SZ_Clear (&net_message); - SZ_Write (&net_message, &sock->receiveMessage[4], length); - - length = IntAlign(length + 4); - sock->receiveMessageLength -= length; - - if (sock->receiveMessageLength) - memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength); - - if (sock->driverdata && ret == 1) - ((qsocket_t *)sock->driverdata)->canSend = true; - - return ret; -} - - -int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data) -{ - qbyte *buffer; - int *bufferLength; - - if (!sock->driverdata) - return -1; - - bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; - - if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE) - Host_Error("Loop_SendMessage: overflow\n"); - - buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; - - // message type - *buffer++ = 1; - - // length - *buffer++ = data->cursize & 0xff; - *buffer++ = data->cursize >> 8; - - // align - buffer++; - - // message - memcpy(buffer, data->data, data->cursize); - *bufferLength = IntAlign(*bufferLength + data->cursize + 4); - - sock->canSend = false; - return 1; -} - - -int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) -{ - qbyte *buffer; - int *bufferLength; - - if (!sock->driverdata) - return -1; - - bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; - - // LordHavoc: added an extra sizeof(qbyte) to account for alignment - if ((*bufferLength + data->cursize + sizeof(qbyte) + sizeof(short) + sizeof(qbyte)) > NET_MAXMESSAGE) - return 0; - - buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; - - // message type - *buffer++ = 2; - - // length - *buffer++ = data->cursize & 0xff; - *buffer++ = data->cursize >> 8; - - // align - buffer++; - - // message - memcpy(buffer, data->data, data->cursize); - *bufferLength = IntAlign(*bufferLength + data->cursize + 4); - return 1; -} - - -qboolean Loop_CanSendMessage (qsocket_t *sock) -{ - if (!sock->driverdata) - return false; - return sock->canSend; -} - - -qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock) -{ - return true; -} - - -void Loop_Close (qsocket_t *sock) -{ - if (sock->driverdata) - ((qsocket_t *)sock->driverdata)->driverdata = NULL; - sock->receiveMessageLength = 0; - sock->sendMessageLength = 0; - sock->canSend = true; - if (sock == loop_client) - loop_client = NULL; - else - loop_server = NULL; -} - diff --git a/net_loop.h b/net_loop.h deleted file mode 100644 index 0938fb96..00000000 --- a/net_loop.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_loop.h - -#ifndef NET_LOOP_H -#define NET_LOOP_H - -int Loop_Init (void); -void Loop_Listen (qboolean state); -void Loop_SearchForHosts (qboolean xmit); -qboolean Loop_SearchForInetHosts (const char *master); -qsocket_t *Loop_Connect (const char *host); -qsocket_t *Loop_CheckNewConnections (void); -int Loop_GetMessage (qsocket_t *sock); -int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data); -int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); -qboolean Loop_CanSendMessage (qsocket_t *sock); -qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock); -void Loop_Close (qsocket_t *sock); -void Loop_Shutdown (void); -void Loop_Heartbeat (const char *master); - -#endif - diff --git a/net_main.c b/net_main.c deleted file mode 100644 index d0027640..00000000 --- a/net_main.c +++ /dev/null @@ -1,935 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_main.c - -#include "quakedef.h" -#include "net_master.h" - -qsocket_t *net_activeSockets = NULL; -mempool_t *net_mempool; - -qboolean ipxAvailable = false; -qboolean tcpipAvailable = false; - -int net_hostport; -int DEFAULTnet_hostport = 26000; - -char my_ipx_address[NET_NAMELEN]; -char my_tcpip_address[NET_NAMELEN]; - -static qboolean listening = false; - -qboolean slistInProgress = false; -qboolean slistSilent = false; -qboolean slistLocal = true; -static double slistStartTime; -static int slistLastShown; - -static void Slist_Send(void); -static void Slist_Poll(void); -PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send}; -PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll}; - -static void InetSlist_Send(void); -static void InetSlist_Poll(void); -PollProcedure inetSlistSendProcedure = {NULL, 0.0, InetSlist_Send}; -PollProcedure inetSlistPollProcedure = {NULL, 0.0, InetSlist_Poll}; - - -sizebuf_t net_message; -int net_activeconnections = 0; - -int messagesSent = 0; -int messagesReceived = 0; -int unreliableMessagesSent = 0; -int unreliableMessagesReceived = 0; - -cvar_t net_messagetimeout = {0, "net_messagetimeout","300"}; -cvar_t hostname = {CVAR_SAVE, "hostname", "UNNAMED"}; -cvar_t developer_networking = {0, "developer_networking", "0"}; - -qboolean configRestored = false; - -// these two macros are to make the code more readable -#define sfunc net_drivers[sock->driver] -#define dfunc net_drivers[net_driverlevel] - -int net_driverlevel; - -/* -#define SLSERVERS 1024 -#define SLNAME 40 -#define SLMAPNAME 16 -#define SLMODNAME 16 -typedef struct slserver_s -{ - unsigned int ipaddr; - unsigned short port; - unsigned short ping; - char name[SLNAME]; - char mapname[SLMAPNAME]; - char modname[SLMODNAME]; -} -slserver_t; - -slserver_t sl_server[SLSERVERS]; -int sl_numservers = 0; - -void SL_ClearServers(void) -{ - sl_numservers = 0; -} - -slserver_t *SL_FindServer(unsigned int ipaddr, unsigned short port) -{ - int i; - slserver_t *sl; - for (i = 0, sl = sl_server;i < sl_numservers;i++, sl++) - if (sl->ipaddr == ipaddr && sl->port == port) - return; -} - -void SL_AddServer(unsigned int ipaddr, unsigned short port) -{ - if (SL_FindServer(ipaddr, port)) - return; - memset(sl_server + sl_numservers, 0, sizeof(slserver_t)); - sl_server[sl_numservers].ipaddr = ipaddr; - sl_server[sl_numservers].port = port; - sl_server[sl_numservers].ping = 0xFFFF; - sl_numservers++; -} - -void SL_UpdateServerName(unsigned int ipaddr, unsigned short port, const char *name); -{ - int namelen; - slserver_t *sl; - sl = SL_FindServer(ipaddr, port); - if (sl == NULL) - return; - memset(sl->name, 0, sizeof(sl->name)); - namelen = strlen(name); - if (namelen > sizeof(sl->name) - 1) - namelen = sizeof(sl->name) - 1; - if (namelen) - memcpy(sl->name, name, namelen); -} - -void SL_UpdateServerModName(unsigned int ipaddr, unsigned short port, const char *name); -{ - int namelen; - slserver_t *sl; - sl = SL_FindServer(ipaddr, port); - if (sl == NULL) - return; - memset(sl->modname, 0, sizeof(sl->modname)); - namelen = strlen(name); - if (namelen > sizeof(sl->modname) - 1) - namelen = sizeof(sl->modname) - 1; - if (namelen) - memcpy(sl->modname, name, namelen); -} - -void SL_UpdateServerMapName(unsigned int ipaddr, unsigned short port, const char *name); -{ - int namelen; - slserver_t *sl; - sl = SL_FindServer(ipaddr, port); - if (sl == NULL) - return; - memset(sl->mapname, 0, sizeof(sl->mapname)); - namelen = strlen(name); - if (namelen > sizeof(sl->mapname) - 1) - namelen = sizeof(sl->mapname) - 1; - if (namelen) - memcpy(sl->mapname, name, namelen); -} - -void SL_UpdateServerPing(unsigned int ipaddr, unsigned short port, float ping); -{ - int i; - slserver_t *sl; - sl = SL_FindServer(ipaddr, port); - if (sl == NULL) - return; - i = ping * 1000.0; - sl->ping = bound(0, i, 9999); -} -*/ - - -double net_time; - -double SetNetTime(void) -{ - net_time = Sys_DoubleTime(); - return net_time; -} - - -/* -=================== -NET_NewQSocket - -Called by drivers when a new communications endpoint is required -The sequence and buffer fields will be filled in properly -=================== -*/ -qsocket_t *NET_NewQSocket (void) -{ - qsocket_t *sock; - - if (net_activeconnections >= svs.maxclients) - return NULL; - - sock = Mem_Alloc(net_mempool, sizeof(qsocket_t)); - - // add it to active list - sock->next = net_activeSockets; - net_activeSockets = sock; - - sock->disconnected = false; - sock->connecttime = net_time; - strcpy (sock->address,"UNSET ADDRESS"); - sock->driver = net_driverlevel; - sock->socket = 0; - sock->driverdata = NULL; - sock->canSend = true; - sock->sendNext = false; - sock->lastMessageTime = net_time; - sock->ackSequence = 0; - sock->sendSequence = 0; - sock->unreliableSendSequence = 0; - sock->sendMessageLength = 0; - sock->receiveSequence = 0; - sock->unreliableReceiveSequence = 0; - sock->receiveMessageLength = 0; - - return sock; -} - - -void NET_FreeQSocket(qsocket_t *sock) -{ - qsocket_t *s; - - // remove it from active list - if (sock == net_activeSockets) - net_activeSockets = net_activeSockets->next; - else - { - for (s = net_activeSockets; s; s = s->next) - if (s->next == sock) - { - s->next = sock->next; - break; - } - if (!s) - Sys_Error ("NET_FreeQSocket: not active\n"); - } - - Mem_Free(sock); -} - - -static void NET_Listen_f (void) -{ - if (Cmd_Argc () != 2) - { - Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0); - return; - } - - listening = atoi(Cmd_Argv(1)) ? true : false; - - for (net_driverlevel=0 ; net_driverlevel 1) && (!listening)) - Cbuf_AddText ("listen 1\n"); - - SV_SetMaxClients(n); -} - - -static void NET_Port_f (void) -{ - int n; - - if (Cmd_Argc () != 2) - { - Con_Printf ("\"port\" is \"%u\"\n", net_hostport); - return; - } - - n = atoi(Cmd_Argv(1)); - if (n < 1 || n > 65534) - { - Con_Printf ("Bad value, must be between 1 and 65534\n"); - return; - } - - DEFAULTnet_hostport = n; - net_hostport = n; - - if (listening) - { - // force a change to the new port - Cbuf_AddText ("listen 0\n"); - Cbuf_AddText ("listen 1\n"); - } -} - - -static void NET_Heartbeat_f (void) -{ - NET_Heartbeat (2); -} - - -static void PrintSlistHeader(void) -{ - Con_Printf("Server Address Name/Description Map Users\n"); - Con_Printf("--------------------- ---------------------------------- --------------- -----\n"); - slistLastShown = 0; -} - - -static void PrintSlist(void) -{ - int n; - for (n = slistLastShown; n < hostCacheCount; n++) - Con_Printf("%-21.21s %-34.34s %-15.15s %2u/%2u\n", hostcache[n].cname, hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers); - slistLastShown = n; -} - - -static void PrintSlistTrailer(void) -{ - if (hostCacheCount) - Con_Printf("== end list ==\n\n"); - else - Con_Printf("No %s servers found.\n\n", gamename); -} - - -void NET_SlistCommon (PollProcedure *sendProcedure, PollProcedure *pollProcedure) -{ - if (slistInProgress) - return; - - if (! slistSilent) - { - Con_Printf("Looking for %s servers...\n", gamename); - PrintSlistHeader(); - } - - slistInProgress = true; - slistStartTime = Sys_DoubleTime(); - - SchedulePollProcedure(sendProcedure, 0.0); - SchedulePollProcedure(pollProcedure, 0.1); - - hostCacheCount = 0; -} - - -void NET_Slist_f (void) -{ - NET_SlistCommon (&slistSendProcedure, &slistPollProcedure); -} - - -void NET_InetSlist_f (void) -{ - NET_SlistCommon (&inetSlistSendProcedure, &inetSlistPollProcedure); -} - - -static void Slist_Send(void) -{ - for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) - { - if (!slistLocal && net_driverlevel == 0) - continue; - if (net_drivers[net_driverlevel].initialized == false) - continue; - dfunc.SearchForHosts (true); - } - - if ((Sys_DoubleTime() - slistStartTime) < 0.5) - SchedulePollProcedure(&slistSendProcedure, 0.75); -} - - -static void Slist_Poll(void) -{ - for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) - { - if (!slistLocal && net_driverlevel == 0) - continue; - if (net_drivers[net_driverlevel].initialized == false) - continue; - dfunc.SearchForHosts (false); - } - - if (! slistSilent) - PrintSlist(); - - if ((Sys_DoubleTime() - slistStartTime) < 1.5) - { - SchedulePollProcedure(&slistPollProcedure, 0.1); - return; - } - - if (! slistSilent) - PrintSlistTrailer(); - slistInProgress = false; - slistSilent = false; - slistLocal = true; -} - - -static void InetSlist_Send(void) -{ - const char* host; - - if (!slistInProgress) - return; - - while ((host = Master_BuildGetServers ()) != NULL) - { - for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) - { - if (!slistLocal && net_driverlevel == 0) - continue; - if (net_drivers[net_driverlevel].initialized == false) - continue; - dfunc.SearchForInetHosts (host); - } - } - - if ((Sys_DoubleTime() - slistStartTime) < 3.5) - SchedulePollProcedure(&inetSlistSendProcedure, 1.0); -} - - -static void InetSlist_Poll(void) -{ - for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) - { - if (!slistLocal && net_driverlevel == 0) - continue; - if (net_drivers[net_driverlevel].initialized == false) - continue; - // We stop as soon as we have one answer (FIXME: bad...) - if (dfunc.SearchForInetHosts (NULL)) - slistInProgress = false; - } - - if (! slistSilent) - PrintSlist(); - - if (slistInProgress && (Sys_DoubleTime() - slistStartTime) < 4.0) - { - SchedulePollProcedure(&inetSlistPollProcedure, 0.1); - return; - } - - if (! slistSilent) - PrintSlistTrailer(); - slistInProgress = false; - slistSilent = false; - slistLocal = true; -} - - -/* -=================== -NET_Connect -=================== -*/ - -int hostCacheCount = 0; -hostcache_t hostcache[HOSTCACHESIZE]; - -qsocket_t *NET_Connect (char *host) -{ - qsocket_t *ret; - - if (host == NULL || *host == 0) - return NULL; - - SetNetTime(); - - if (host && strcasecmp (host, "local") == 0) - { - net_driverlevel = 0; - return dfunc.Connect (host); - } - - for (net_driverlevel = 0;net_driverlevel < net_numdrivers;net_driverlevel++) - { - if (net_drivers[net_driverlevel].initialized == false) - continue; - ret = dfunc.Connect (host); - if (ret) - return ret; - } - - return NULL; -} - - -/* -=================== -NET_CheckNewConnections -=================== -*/ - -qsocket_t *NET_CheckNewConnections (void) -{ - qsocket_t *ret; - - SetNetTime(); - - for (net_driverlevel=0 ; net_driverleveldisconnected) - return; - - SetNetTime(); - - // call the driver_Close function - sfunc.Close (sock); - - NET_FreeQSocket(sock); -} - - -/* -================= -NET_GetMessage - -If there is a complete message, return it in net_message - -returns 0 if no data is waiting -returns 1 if a message was received -returns -1 if connection is invalid -================= -*/ - -extern void PrintStats(qsocket_t *s); - -int NET_GetMessage (qsocket_t *sock) -{ - int ret; - - if (!sock) - return -1; - - if (sock->disconnected) - { - Con_Printf("NET_GetMessage: disconnected socket\n"); - return -1; - } - - SetNetTime(); - - ret = sfunc.QGetMessage(sock); - - // see if this connection has timed out - if (ret == 0 && sock->driver) - { - if (net_time - sock->lastMessageTime > net_messagetimeout.value) - { - NET_Close(sock); - return -1; - } - } - - - if (ret > 0) - { - if (sock->driver) - { - sock->lastMessageTime = net_time; - if (ret == 1) - messagesReceived++; - else if (ret == 2) - unreliableMessagesReceived++; - } - } - - return ret; -} - - -/* -================== -NET_SendMessage - -Try to send a complete length+message unit over the reliable stream. -returns 0 if the message cannot be delivered reliably, but the connection - is still considered valid -returns 1 if the message was sent properly -returns -1 if the connection died -================== -*/ -int NET_SendMessage (qsocket_t *sock, sizebuf_t *data) -{ - int r; - - if (!sock) - return -1; - - if (sock->disconnected) - { - Con_Printf("NET_SendMessage: disconnected socket\n"); - return -1; - } - - SetNetTime(); - r = sfunc.QSendMessage(sock, data); - if (r == 1 && sock->driver) - messagesSent++; - - return r; -} - - -int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) -{ - int r; - - if (!sock) - return -1; - - if (sock->disconnected) - { - Con_Printf("NET_SendMessage: disconnected socket\n"); - return -1; - } - - SetNetTime(); - r = sfunc.SendUnreliableMessage(sock, data); - if (r == 1 && sock->driver) - unreliableMessagesSent++; - - return r; -} - - -/* -================== -NET_CanSendMessage - -Returns true or false if the given qsocket can currently accept a -message to be transmitted. -================== -*/ -qboolean NET_CanSendMessage (qsocket_t *sock) -{ - int r; - - if (!sock) - return false; - - if (sock->disconnected) - return false; - - SetNetTime(); - - r = sfunc.CanSendMessage(sock); - - return r; -} - - -/* -==================== -NET_Heartbeat - -Send an heartbeat to the master server(s) -==================== -*/ -void NET_Heartbeat (int priority) -{ - const char* host; - - if (! Master_AllowHeartbeat (priority)) - return; - - while ((host = Master_BuildHeartbeat ()) != NULL) - { - for (net_driverlevel=0 ; net_driverlevelnetconnection && host_client->active) - { - if (host_client->netconnection->driver == 0) - NET_SendMessage(host_client->netconnection, data); - else - state[i] = 0; - } - } - - // for every player (simultaneously) wait for the first CanSendMessage - // and send the message, then wait for a second CanSendMessage (verifying - // it was received) - start = Sys_DoubleTime(); - do - { - count = 0; - for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) - { - if (state[i] < 2) - { - count++; - // need to send to this one - if (NET_CanSendMessage (host_client->netconnection)) - { - if (state[i] == 0 && NET_SendMessage (host_client->netconnection, data) == -1) - state[i] = 2; // connection lost - state[i]++; - } - else - NET_GetMessage (host_client->netconnection); - } - } - } - while (count && (Sys_DoubleTime() - start) < blocktime); - return count; -} - - -//============================================================================= - -/* -==================== -NET_Init -==================== -*/ - -void NET_Init (void) -{ - int i; - int controlSocket; - - i = COM_CheckParm ("-port"); - if (!i) - i = COM_CheckParm ("-udpport"); - if (!i) - i = COM_CheckParm ("-ipxport"); - - if (i) - { - if (i < com_argc-1) - DEFAULTnet_hostport = atoi (com_argv[i+1]); - else - Sys_Error ("NET_Init: you must specify a number after -port"); - } - net_hostport = DEFAULTnet_hostport; - - if (COM_CheckParm("-listen") || cls.state == ca_dedicated || gamemode == GAME_TRANSFUSION) - listening = true; - - SetNetTime(); - - net_mempool = Mem_AllocPool("qsocket"); - - // allocate space for network message buffer - SZ_Alloc (&net_message, NET_MAXMESSAGE, "net_message"); - - Cvar_RegisterVariable (&net_messagetimeout); - Cvar_RegisterVariable (&hostname); - Cvar_RegisterVariable (&developer_networking); - - Cmd_AddCommand ("net_slist", NET_Slist_f); - Cmd_AddCommand ("net_inetslist", NET_InetSlist_f); - Cmd_AddCommand ("listen", NET_Listen_f); - Cmd_AddCommand ("maxplayers", MaxPlayers_f); - Cmd_AddCommand ("port", NET_Port_f); - Cmd_AddCommand ("heartbeat", NET_Heartbeat_f); - - // initialize all the drivers - for (net_driverlevel=0 ; net_driverlevelnext) - { - if (pp->nextTime > net_time) - break; - pollProcedureList = pp->next; - pp->procedure(pp->arg); - } -} - - -void SchedulePollProcedure(PollProcedure *proc, double timeOffset) -{ - PollProcedure *pp, *prev; - - proc->nextTime = Sys_DoubleTime() + timeOffset; - for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next) - { - if (pp->nextTime >= proc->nextTime) - break; - prev = pp; - } - - if (prev == NULL) - { - proc->next = pollProcedureList; - pollProcedureList = proc; - return; - } - - proc->next = pp; - prev->next = proc; -} - diff --git a/net_master.c b/net_master.c deleted file mode 100644 index 52f6487a..00000000 --- a/net_master.c +++ /dev/null @@ -1,300 +0,0 @@ -/* -Copyright (C) 2002 Mathieu Olivier - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_master.c - -#include "quakedef.h" - - -cvar_t sv_public = {0, "sv_public", "0"}; -cvar_t sv_heartbeatperiod = {CVAR_SAVE, "sv_heartbeatperiod", "180"}; - -cvar_t sv_masters [] = -{ - {CVAR_SAVE, "sv_master1", ""}, - {CVAR_SAVE, "sv_master2", ""}, - {CVAR_SAVE, "sv_master3", ""}, - {CVAR_SAVE, "sv_master4", ""}, - {0, "sv_masterextra1", "198.88.152.4"}, - {0, "sv_masterextra2", "68.102.242.12"} -}; - -static double nextheartbeattime = 0; - - -/* -==================== -Master_AllowHeartbeat - -Allow (or not) NET_Heartbeat to proceed depending on various factors -==================== -*/ -qboolean Master_AllowHeartbeat (int priority) -{ - // LordHavoc: make advertising optional - if (!sv_public.integer) - return false; - // LordHavoc: don't advertise singleplayer games - if (svs.maxclients < 2) - return false; - // if it's a state change (client connected), limit next heartbeat to no - // more than 30 sec in the future - if (priority == 1 && nextheartbeattime > realtime + 30.0) - nextheartbeattime = realtime + 30.0; - if (priority <= 1 && realtime < nextheartbeattime) - return false; - // limit heartbeatperiod to 30 to 270 second range, - // lower limit is to avoid abusing master servers with excess traffic, - // upper limit is to avoid timing out on the master server (which uses - // 300 sec timeout) - if (sv_heartbeatperiod.value < 30) - Cvar_SetValueQuick(&sv_heartbeatperiod, 30); - if (sv_heartbeatperiod.value > 270) - Cvar_SetValueQuick(&sv_heartbeatperiod, 270); - // send a heartbeat as often as the admin wants - nextheartbeattime = realtime + sv_heartbeatperiod.value; - return true; -} - - -/* -==================== -Master_BuildGetServers - -Build a getservers request for a master server -==================== -*/ -const char* Master_BuildGetServers (void) -{ - static int nextmaster = 0; - cvar_t* sv_master; - char request [256]; - - if (nextmaster >= (int)(sizeof (sv_masters) / sizeof (sv_masters[0]))) - { - nextmaster = 0; - return NULL; - } - - // find a non-empty master server address in the list - for(;;) - { - sv_master = &sv_masters[nextmaster++]; - if (sv_master->string[0]) - break; - if (nextmaster >= (int)(sizeof (sv_masters) / sizeof (sv_masters[0]))) - { - nextmaster = 0; - return NULL; - } - } - - // Build the heartbeat - snprintf (request, sizeof (request), "getservers %s %u empty full\x0A", gamename, NET_PROTOCOL_VERSION); - SZ_Clear (&net_message); - MSG_WriteLong (&net_message, -1); - MSG_WriteString (&net_message, request); - - net_message.cursize--; // we don't send the trailing '\0' - - return sv_master->string; -} - - -/* -==================== -Master_BuildHeartbeat - -Build an heartbeat for a master server -==================== -*/ -const char* Master_BuildHeartbeat (void) -{ - static int nextmaster = 0; - cvar_t* sv_master; - - if (nextmaster >= (int)(sizeof (sv_masters) / sizeof (sv_masters[0]))) - { - nextmaster = 0; - return NULL; - } - - // find a non-empty master server address in the list - for(;;) - { - sv_master = &sv_masters[nextmaster++]; - if (sv_master->string[0]) - break; - if (nextmaster >= (int)(sizeof (sv_masters) / sizeof (sv_masters[0]))) - { - nextmaster = 0; - return NULL; - } - } - - // Build the heartbeat - SZ_Clear (&net_message); - MSG_WriteLong (&net_message, -1); - MSG_WriteString (&net_message, "heartbeat DarkPlaces\x0A"); - - net_message.cursize--; // we don't send the trailing '\0' - - return sv_master->string; -} - - -/* -==================== -Master_HandleMessage - -Handle the master server messages -==================== -*/ -int Master_HandleMessage (void) -{ - const char* string = MSG_ReadString (); - - // If it's a "getinfo" request - if (!strncmp (string, "getinfo", 7)) - { - char response [512]; - size_t length; - - length = snprintf (response, sizeof (response), "infoResponse\x0A" - "\\gamename\\%s\\modname\\%s\\sv_maxclients\\%d" - "\\clients\\%d\\mapname\\%s\\hostname\\%s\\protocol\\%d", - gamename, com_modname, svs.maxclients, net_activeconnections, - sv.name, hostname.string, NET_PROTOCOL_VERSION); - - // Too long to fit into the buffer? - if (length >= sizeof (response)) - return -1; - - // If there was a challenge in the getinfo message - if (string[7] == ' ') - { - string += 8; // skip the header and the space - - // If the challenge wouldn't fit into the buffer - if (length + 11 + strlen (string) >= sizeof (response)) - return -1; - - sprintf (response + length, "\\challenge\\%s", string); - } - - SZ_Clear (&net_message); - MSG_WriteLong (&net_message, -1); - MSG_WriteString (&net_message, response); - - return net_message.cursize - 1; - } - - return 0; -} - - -/* -==================== -Master_Init - -Initialize the code that handles master server requests and reponses -==================== -*/ -void Master_Init (void) -{ - unsigned int ind; - Cvar_RegisterVariable (&sv_public); - Cvar_RegisterVariable (&sv_heartbeatperiod); - for (ind = 0; ind < sizeof (sv_masters) / sizeof (sv_masters[0]); ind++) - Cvar_RegisterVariable (&sv_masters[ind]); -} - - -/* -==================== -Master_ParseServerList - -Parse getserverResponse messages -Returns true if it was a valid getserversResponse -==================== -*/ -int Master_ParseServerList (net_landriver_t* dfunc) -{ - int servercount = 0; - int control; - qbyte* servers; - qbyte* crtserver; - struct qsockaddr svaddr; - char ipstring [32]; - char string[32]; - - if (developer.integer) - { - Con_Printf("Master_ParseServerList: packet received:\n"); - SZ_HexDumpToConsole(&net_message); - } - - if (net_message.cursize < 23) - return 0; - - // is the cache full? - if (hostCacheCount == HOSTCACHESIZE) - return 0; - - MSG_BeginReading (); - control = MSG_ReadBigLong(); - if (control != -1) - return 0; - - if (MSG_ReadBytes(19, string) < 19 || memcmp(string, "getserversResponse\\", 19)) - return 0; - - crtserver = servers = Z_Malloc (net_message.cursize - 23); - memcpy (servers , net_message.data + 23, net_message.cursize - 23); - - // Extract the IP addresses - while ((crtserver[0] != 0xFF || crtserver[1] != 0xFF || crtserver[2] != 0xFF || crtserver[3] != 0xFF) && (crtserver[4] != 0 || crtserver[5] != 0)) - { - // LordHavoc: FIXME: this could be much faster than converting to a string and back - // LordHavoc: FIXME: this code is very UDP specific, perhaps it should be part of net_udp? - sprintf (ipstring, "%u.%u.%u.%u:%u", crtserver[0], crtserver[1], crtserver[2], crtserver[3], (crtserver[4] << 8) | crtserver[5]); - dfunc->GetAddrFromName (ipstring, &svaddr); - Con_DPrintf("Requesting info from server %s\n", ipstring); - - // Send a request at this address - SZ_Clear(&net_message); - MSG_WriteLong(&net_message, 0); // save space for the header, filled in later - MSG_WriteByte(&net_message, CCREQ_SERVER_INFO); - MSG_WriteString(&net_message, "QUAKE"); - MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); - dfunc->Write(dfunc->controlSock, net_message.data, net_message.cursize, &svaddr); - SZ_Clear(&net_message); - - servercount++; - - if (crtserver[6] != '\\') - break; - crtserver += 7; - } - - Z_Free (servers); - - return servercount; -} diff --git a/net_master.h b/net_master.h deleted file mode 100644 index a7c3732c..00000000 --- a/net_master.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright (C) 2002 Mathieu Olivier - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_master.h - -#ifndef NET_MASTER_H -#define NET_MASTER_H - -#define MASTER_PORT 27950 - -qboolean Master_AllowHeartbeat (int priority); -const char* Master_BuildGetServers (void); -const char* Master_BuildHeartbeat (void); -int Master_HandleMessage (void); -void Master_Init (void); -int Master_ParseServerList (net_landriver_t* dfunc); - -#endif diff --git a/net_udp.c b/net_udp.c deleted file mode 100644 index 3dbb8957..00000000 --- a/net_udp.c +++ /dev/null @@ -1,492 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#include "quakedef.h" -#include "net_udp.h" -#ifdef WIN32 -#include "winquake.h" -#define MAXHOSTNAMELEN 256 -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __sun__ -#include -#endif - -#ifdef NeXT -#include -#endif -#endif - -static int net_acceptsocket = -1; // socket for fielding new connections -static int net_controlsocket; -static int net_broadcastsocket = 0; -static struct qsockaddr broadcastaddr; - -static union {unsigned int i;unsigned char d[4];} myAddr; - -//============================================================================= - -#ifdef WIN32 -WSADATA winsockdata; -#endif - -int UDP_Init (void) -{ - int i, j; - struct hostent *local; - char buff[MAXHOSTNAMELEN]; - - if (COM_CheckParm ("-noudp")) - return -1; - -#ifdef WIN32 - if (WSAStartup (MAKEWORD(1, 1), &winsockdata)) - { - Con_SafePrintf ("Winsock initialization failed.\n"); - return -1; - } -#endif - - // loopback as a worst case fallback - myAddr.i = htonl(INADDR_ANY); - - net_controlsocket = -1; - for (j = 0;net_controlsocket == -1;j++) - { - switch(j) - { - case 0: - if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) - myAddr.i = inet_addr(com_argv[i+1]); - break; - case 1: - myAddr.i = htonl(INADDR_ANY); - break; - case 2: - if (gethostname(buff, MAXHOSTNAMELEN) != -1) - { - buff[MAXHOSTNAMELEN - 1] = 0; - local = gethostbyname(buff); - if (local != NULL) - myAddr.i = *((int *)local->h_addr_list[0]); - else - continue; - } - else - continue; - break; - default: - Con_Printf("UDP_Init: Giving up, UDP networking support disabled.\n"); -#ifdef WIN32 - WSACleanup (); -#endif - return -1; - } - - if (myAddr.i == htonl(INADDR_LOOPBACK)) - sprintf(my_tcpip_address, "INADDR_LOOPBACK"); - else if (myAddr.i == htonl(INADDR_ANY)) - sprintf(my_tcpip_address, "INADDR_ANY"); - else if (myAddr.i == htonl(INADDR_NONE)) - sprintf(my_tcpip_address, "INADDR_NONE"); - else - sprintf(my_tcpip_address, "%d.%d.%d.%d", myAddr.d[0], myAddr.d[1], myAddr.d[2], myAddr.d[3]); - Con_Printf("UDP_Init: Binding to IP Interface Address of %s... ", my_tcpip_address); - if ((net_controlsocket = UDP_OpenSocket (0)) == -1) - Con_Printf("failed\n"); - else - Con_Printf("succeeded\n"); - } - - ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; - ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = htonl(INADDR_BROADCAST); - ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((unsigned short)net_hostport); - - Con_Printf("UDP Initialized\n"); - tcpipAvailable = true; - - return net_controlsocket; -} - -//============================================================================= - -void UDP_Shutdown (void) -{ - UDP_Listen (false); - UDP_CloseSocket (net_controlsocket); -#ifdef WIN32 - WSACleanup (); -#endif -} - -//============================================================================= - -void UDP_Listen (qboolean state) -{ - // enable listening - if (state) - { - if (net_acceptsocket != -1) - return; - if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1) - Sys_Error ("UDP_Listen: Unable to open accept socket\n"); - return; - } - - // disable listening - if (net_acceptsocket == -1) - return; - UDP_CloseSocket (net_acceptsocket); - net_acceptsocket = -1; -} - -//============================================================================= - -int UDP_OpenSocket (int port) -{ - int newsocket; - struct sockaddr_in address; - - if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) - return -1; - - { -#ifdef WIN32 - u_long _true = 1; - if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) - { - closesocket (newsocket); -#else - char _true = 1; - if (ioctl (newsocket, FIONBIO, &_true) == -1) - { - close (newsocket); -#endif - Sys_Error("UDP_OpenSocket: unable to do a ioctl FIONBIO on the socket\n"); - } - } - - address.sin_family = AF_INET; - address.sin_addr.s_addr = myAddr.i; - address.sin_port = htons((unsigned short)port); - if (bind(newsocket, (void *)&address, sizeof(address)) == -1) - { -#ifdef WIN32 - closesocket(newsocket); -#else - close(newsocket); -#endif - Sys_Error ("UDP_OpenSocket: Unable to bind to %s", UDP_AddrToString((struct qsockaddr *)&address)); - } - - return newsocket; -} - -//============================================================================= - -int UDP_CloseSocket (int socket) -{ - if (net_broadcastsocket == socket) - net_broadcastsocket = 0; -#ifdef WIN32 - return closesocket (socket); -#else - return close (socket); -#endif -} - -//============================================================================= - -int UDP_Connect (int socket, struct qsockaddr *addr) -{ - return 0; -} - -//============================================================================= - -int UDP_CheckNewConnections (void) -{ - char buf[4096]; -#ifndef WIN32 - unsigned long available; - struct sockaddr_in from; - socklen_t fromlen; -#endif - - if (net_acceptsocket == -1) - return -1; - -#ifdef WIN32 - if (recvfrom (net_acceptsocket, buf, sizeof(buf), MSG_PEEK, NULL, NULL) >= 0) - return net_acceptsocket; -#else - if (ioctl (net_acceptsocket, FIONREAD, &available) == -1) - Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n"); - if (available) - return net_acceptsocket; - recvfrom (net_acceptsocket, buf, 0, 0, (struct sockaddr *) &from, &fromlen); -#endif - return -1; -} - -//============================================================================= - -int UDP_Recv (qbyte *buf, int len, struct qsockaddr *addr) -{ - return UDP_Read (net_acceptsocket, buf, len, addr); -} - -//============================================================================= - -int UDP_Send (qbyte *buf, int len, struct qsockaddr *addr) -{ - return UDP_Write (net_acceptsocket, buf, len, addr); -} - -//============================================================================= - -int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr) -{ - int addrlen = sizeof (struct qsockaddr); - int ret; - - ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); - if (ret == -1) - { -#ifdef WIN32 - int e = WSAGetLastError(); - if (e == WSAEWOULDBLOCK || e == WSAECONNREFUSED) - return 0; - Con_Printf("UDP_Read(%i, %p, %i, <%s>): WSAGetLastError == %i\n", socket, buf, len, UDP_AddrToString(addr), e); -#else - if (errno == EWOULDBLOCK || errno == ECONNREFUSED) - return 0; - Con_Printf("UDP_Read(%i, %p, %i, <%s>): errno == %i (%s)\n", socket, buf, len, UDP_AddrToString(addr), errno, strerror(errno)); -#endif - } - else if (developer_networking.integer) - { - Con_Printf("UDP_Read(%i, %p, %i, <%s>) = %i\n", socket, buf, len, UDP_AddrToString(addr), ret); - Com_HexDumpToConsole(buf, ret); - } - - return ret; -} - -//============================================================================= - -int UDP_MakeSocketBroadcastCapable (int socket) -{ - int i = 1; - - // make this socket broadcast capable - if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) - return -1; - net_broadcastsocket = socket; - - return 0; -} - -//============================================================================= - -int UDP_Broadcast (int socket, qbyte *buf, int len) -{ - int ret; - - if (socket != net_broadcastsocket) - { - if (net_broadcastsocket != 0) - Sys_Error("Attempted to use multiple broadcasts sockets\n"); - ret = UDP_MakeSocketBroadcastCapable (socket); - if (ret == -1) - { - Con_Printf("Unable to make socket broadcast capable\n"); - return ret; - } - } - - return UDP_Write (socket, buf, len, &broadcastaddr); -} - -//============================================================================= - -int UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr) -{ - int ret; - - if (developer_networking.integer) - { - Con_Printf("UDP_Write(%i, %p, %i, <%s>)\n", socket, buf, len, UDP_AddrToString(addr)); - Com_HexDumpToConsole(buf, len); - } - - ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); - if (ret == -1) - { -#ifdef WIN32 - int e = WSAGetLastError(); - if (e == WSAEWOULDBLOCK) - return 0; - Con_Printf("UDP_Write(%i, %p, %i, <%s>): WSAGetLastError == %i\n", socket, buf, len, UDP_AddrToString(addr), e); -#else - if (errno == EWOULDBLOCK) - return 0; - Con_Printf("UDP_Write(%i, %p, %i, <%s>): errno == %i (%s)\n", socket, buf, len, UDP_AddrToString(addr), errno, strerror(errno)); -#endif - } - return ret; -} - -//============================================================================= - -char *UDP_AddrToString (const struct qsockaddr *addr) -{ - static char buffer[22]; // only 22 needed (3 + 1 + 3 + 1 + 3 + 1 + 3 + 1 + 5 + null) - unsigned char *ip = (char *)(&((struct sockaddr_in *)addr)->sin_addr.s_addr); - sprintf(buffer, "%d.%d.%d.%d:%d", ip[0], ip[1], ip[2], ip[3], ntohs(((struct sockaddr_in *)addr)->sin_port)); - return buffer; -} - -//============================================================================= - -int UDP_StringToAddr (const char *string, struct qsockaddr *addr) -{ - int ha[4], hp, ipaddr, j, numbers; - const char *colon; - - hp = net_hostport; - colon = strrchr(string, ':'); - if (colon) - { - hp = atoi(colon + 1); - if (hp == 0) - hp = net_hostport; - } - numbers = sscanf(string, "%d.%d.%d.%d", &ha[0], &ha[1], &ha[2], &ha[3]); - for (ipaddr = 0, j = 0;j < numbers;j++) - ipaddr = (ipaddr << 8) | ha[j]; - // if the address is incomplete take most important numbers from myAddr - if (numbers < 4) - ipaddr |= ntohl(myAddr.i) & (-1 << (numbers * 8)); - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); - ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)hp); - if (ipaddr == INADDR_ANY) - return -1; - else - return 0; -} - -//============================================================================= - -int UDP_GetSocketAddr (int socket, struct qsockaddr *addr) -{ - int ret; - int addrlen = sizeof(struct qsockaddr); - memset(addr, 0, sizeof(struct qsockaddr)); - ret = getsockname(socket, (struct sockaddr *)addr, &addrlen); - if (ret == -1) - { -#ifdef WIN32 - int e = WSAGetLastError(); - Con_Printf("UDP_GetSocketAddr: WASGetLastError == %i\n", e); -#else - Con_Printf("UDP_GetSocketAddr: errno == %i (%s)\n", errno, strerror(errno)); -#endif - } - return ret; -} - -//============================================================================= - -int UDP_GetNameFromAddr (const struct qsockaddr *addr, char *name) -{ - struct hostent *hostentry; - - hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); - if (hostentry) - { - strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); - return 0; - } - - strcpy (name, UDP_AddrToString (addr)); - return 0; -} - -//============================================================================= - -int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr) -{ - struct hostent *hostentry; - - if (name[0] >= '0' && name[0] <= '9') - return UDP_StringToAddr (name, addr); - - hostentry = gethostbyname (name); - if (!hostentry) - return -1; - - addr->sa_family = AF_INET; - ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)net_hostport); - ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; - - return 0; -} - -//============================================================================= - -int UDP_AddrCompare (const struct qsockaddr *addr1, const struct qsockaddr *addr2) -{ - if (addr1->sa_family != addr2->sa_family) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) - return -1; - - if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) - return 1; - - return 0; -} - -//============================================================================= - -int UDP_GetSocketPort (struct qsockaddr *addr) -{ - return ntohs(((struct sockaddr_in *)addr)->sin_port); -} - - -int UDP_SetSocketPort (struct qsockaddr *addr, int port) -{ - ((struct sockaddr_in *)addr)->sin_port = htons((unsigned short)port); - return 0; -} - diff --git a/net_udp.h b/net_udp.h deleted file mode 100644 index dbd66639..00000000 --- a/net_udp.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// net_udp.h - -#ifndef NET_UDP_H -#define NET_UDP_H - -int UDP_Init (void); -void UDP_Shutdown (void); -void UDP_Listen (qboolean state); -int UDP_OpenSocket (int port); -int UDP_CloseSocket (int socket); -int UDP_Connect (int socket, struct qsockaddr *addr); -int UDP_CheckNewConnections (void); -int UDP_Recv (qbyte *buf, int len, struct qsockaddr *addr); -int UDP_Send (qbyte *buf, int len, struct qsockaddr *addr); -int UDP_Read (int socket, qbyte *buf, int len, struct qsockaddr *addr); -int UDP_Write (int socket, qbyte *buf, int len, struct qsockaddr *addr); -int UDP_Broadcast (int socket, qbyte *buf, int len); -char *UDP_AddrToString (const struct qsockaddr *addr); -int UDP_StringToAddr (const char *string, struct qsockaddr *addr); -int UDP_GetSocketAddr (int socket, struct qsockaddr *addr); -int UDP_GetNameFromAddr (const struct qsockaddr *addr, char *name); -int UDP_GetAddrFromName (const char *name, struct qsockaddr *addr); -int UDP_AddrCompare (const struct qsockaddr *addr1, const struct qsockaddr *addr2); -int UDP_GetSocketPort (struct qsockaddr *addr); -int UDP_SetSocketPort (struct qsockaddr *addr, int port); - -#endif - diff --git a/pr_cmds.c b/pr_cmds.c index 04843d7c..ccbb3634 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -2092,8 +2092,9 @@ setcolor(clientent, value) */ void PF_setcolor (void) { - client_t *client; - int entnum, i; + client_t *client; + int entnum, i; + eval_t *val; entnum = G_EDICTNUM(OFS_PARM0); i = G_FLOAT(OFS_PARM1); @@ -2105,7 +2106,10 @@ void PF_setcolor (void) } client = &svs.clients[entnum-1]; + if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors))) + val->_float = i; client->colors = i; + client->old_colors = i; client->edict->v->team = (i & 15) + 1; MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); diff --git a/pr_edict.c b/pr_edict.c index 83a780e6..4acf10b1 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -119,6 +119,7 @@ int eval_movement; int eval_pmodel; int eval_punchvector; int eval_viewzoom; +int eval_clientcolors; mfunction_t *SV_PlayerPhysicsQC; mfunction_t *EndFrameQC; @@ -170,6 +171,7 @@ void FindEdictFieldOffsets(void) eval_pmodel = FindFieldOffset("pmodel"); eval_punchvector = FindFieldOffset("punchvector"); eval_viewzoom = FindFieldOffset("viewzoom"); + eval_clientcolors = FindFieldOffset("clientcolors"); // LordHavoc: allowing QuakeC to override the player movement code SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics"); @@ -1177,7 +1179,8 @@ dpfield_t dpfields[] = {ev_float, "ping"}, {ev_vector, "movement"}, {ev_float, "pmodel"}, - {ev_vector, "punchvector"} + {ev_vector, "punchvector"}, + {ev_float, "clientcolors"} }; /* diff --git a/progs.h b/progs.h index ee5d9e2e..5934f45d 100644 --- a/progs.h +++ b/progs.h @@ -120,6 +120,7 @@ extern int eval_movement; extern int eval_pmodel; extern int eval_punchvector; extern int eval_viewzoom; +extern int eval_clientcolors; #define GETEDICTFIELDVALUE(ed, fieldoffset) (fieldoffset ? (eval_t *)((qbyte *)ed->v + fieldoffset) : NULL) diff --git a/quakedef.h b/quakedef.h index a4ae3929..bd9ca3c1 100644 --- a/quakedef.h +++ b/quakedef.h @@ -152,7 +152,8 @@ extern char *buildstring; // LordHavoc: increased player limit from 16 to 64 #define MAX_SCOREBOARD 64 -#define MAX_SCOREBOARDNAME 32 +// LordHavoc: increased name limit from 32 to 64 characters +#define MAX_SCOREBOARDNAME 64 #define SOUND_CHANNELS 8 @@ -170,7 +171,7 @@ extern char *buildstring; #include "wad.h" #include "draw.h" #include "screen.h" -#include "net.h" +#include "netconn.h" #include "protocol.h" #include "cmd.h" #include "sbar.h" @@ -211,17 +212,17 @@ extern int host_framecount; // not bounded in any way, changed at start of every frame, never reset extern double realtime; -void Host_ClearMemory (void); -void Host_ServerFrame (void); -void Host_InitCommands (void); -void Host_Init (void); +void Host_ClearMemory(void); +void Host_InitCommands(void); +void Host_Init(void); void Host_Shutdown(void); -void Host_Error (const char *error, ...); -void Host_EndGame (const char *message, ...); -void Host_Frame (float time); -void Host_Quit_f (void); -void Host_ClientCommands (const char *fmt, ...); -void Host_ShutdownServer (qboolean crash); +void Host_Error(const char *error, ...); +void Host_EndGame(const char *message, ...); +void Host_Frame(float time); +void Host_Quit_f(void); +void Host_ClientCommands(const char *fmt, ...); +void Host_ShutdownServer(qboolean crash); +void Host_Reconnect_f(void); // skill level for currently loaded level (in case the user changes the cvar while the level is running, this reflects the level actually in use) extern int current_skill; diff --git a/server.h b/server.h index 363a5757..8eb1153d 100644 --- a/server.h +++ b/server.h @@ -108,12 +108,14 @@ typedef struct client_s qboolean dropasap; // only valid before spawned qboolean sendsignon; + // remove this client immediately + qboolean deadsocket; // reliable messages must be sent periodically double last_message; // communications handle - struct qsocket_s *netconnection; + netconn_t *netconnection; // movement usercmd_t cmd; @@ -125,9 +127,6 @@ typedef struct client_s qbyte msgbuf[MAX_DATAGRAM]; // EDICT_NUM(clientnum+1) edict_t *edict; - // for printing to other people - char name[32]; - int colors; float ping_times[NUM_PING_TIMES]; // ping_times[num_pings%NUM_PING_TIMES] @@ -140,18 +139,19 @@ typedef struct client_s // spawn parms are carried from level to level float spawn_parms[NUM_SPAWN_PARMS]; -// client known data for deltas - int old_frags; + // properties that are sent across the network only when changed + char name[64], old_name[64]; + int colors, old_colors; + int frags, old_frags; + // other properties not sent across the network int pmodel; + // visibility state + float visibletime[MAX_EDICTS]; #ifdef QUAKEENTITIES // delta compression state float nextfullupdate[MAX_EDICTS]; -#endif - // visibility state - float visibletime[MAX_EDICTS]; - -#ifndef QUAKEENTITIES +#else entity_database_t entitydatabase; int entityframenumber; // incremented each time an entity frame is sent #endif @@ -273,6 +273,8 @@ void SV_DropClient (qboolean crash); void SV_SendClientMessages (void); void SV_ClearDatagram (void); +void SV_ReadClientMessage(void); + int SV_ModelIndex (const char *name); void SV_SetIdealPitch (void); @@ -280,7 +282,6 @@ void SV_SetIdealPitch (void); void SV_AddUpdates (void); void SV_ClientThink (void); -void SV_AddClientToServer (struct qsocket_s *ret); void SV_ClientPrintf (const char *fmt, ...); void SV_BroadcastPrintf (const char *fmt, ...); @@ -294,7 +295,6 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg); void SV_MoveToGoal (void); -void SV_CheckForNewClients (void); void SV_RunClients (void); void SV_SaveSpawnparms (void); void SV_SpawnServer (const char *server); diff --git a/sv_main.c b/sv_main.c index 3919ddde..fb0049ed 100644 --- a/sv_main.c +++ b/sv_main.c @@ -302,25 +302,22 @@ Initializes a client_t for a new net connection. This will only be called once for a player each game, not once for each level change. ================ */ -void SV_ConnectClient (int clientnum) +void SV_ConnectClient (int clientnum, netconn_t *netconnection) { client_t *client; - struct qsocket_s *netconnection; int i; float spawn_parms[NUM_SPAWN_PARMS]; client = svs.clients + clientnum; - Con_DPrintf ("Client %s connected\n", client->netconnection->address); - // set up the client_t - netconnection = client->netconnection; - if (sv.loadgame) memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms)); memset (client, 0, sizeof(*client)); client->netconnection = netconnection; + Con_DPrintf ("Client %s connected\n", client->netconnection->address); + strcpy (client->name, "unconnected"); client->active = true; client->spawned = false; @@ -333,55 +330,20 @@ void SV_ConnectClient (int clientnum) memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms)); else { - // call the progs to get default spawn parms for the new client + // call the progs to get default spawn parms for the new client PR_ExecuteProgram (pr_global_struct->SetNewParms, "QC function SetNewParms is missing"); for (i=0 ; ispawn_parms[i] = (&pr_global_struct->parm1)[i]; + // set up the edict a bit + ED_ClearEdict(client->edict); + client->edict->v->colormap = NUM_FOR_EDICT(client->edict); + client->edict->v->netname = PR_SetString(client->name); } SV_SendServerinfo (client); } -/* -=================== -SV_CheckForNewClients - -=================== -*/ -void SV_CheckForNewClients (void) -{ - struct qsocket_s *ret; - int i; - -// -// check for new connections -// - while (1) - { - ret = NET_CheckNewConnections (); - if (!ret) - break; - - // - // init a new client structure - // - for (i=0 ; inetconnection, &msg) == -1) + if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1) { SV_DropClient (true);// if the message couldn't send, kick off return false; @@ -1410,31 +1372,74 @@ void SV_UpdateToReliableMessages (void) { int i, j; client_t *client; + eval_t *val; + char *s; // check for changes to be sent over the reliable streams for (i=0, host_client = svs.clients ; iedict; - if (host_client->old_frags != sv_player->v->frags) + s = PR_GetString(sv_player->v->netname); + if (s != host_client->name) + { + if (s == NULL) + s = ""; + // point the string back at host_client->name to keep it safe + strncpy(host_client->name, s, sizeof(host_client->name) - 1); + sv_player->v->netname = PR_SetString(host_client->name); + } + if ((val = GETEDICTFIELDVALUE(sv_player, eval_clientcolors)) && host_client->colors != val->_float) + host_client->colors = val->_float; + host_client->frags = sv_player->v->frags; + if (gamemode == GAME_NEHAHRA) + if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel)) && host_client->pmodel != val->_float) + host_client->pmodel = val->_float; + + // if the fields changed, send messages about the changes + if (strcmp(host_client->old_name, host_client->name)) + { + strcpy(host_client->old_name, host_client->name); + for (j=0, client = svs.clients ; jactive || !client->spawned) + continue; + MSG_WriteByte (&client->message, svc_updatename); + MSG_WriteByte (&client->message, i); + MSG_WriteString (&client->message, host_client->name); + } + } + if (host_client->old_colors != host_client->colors) + { + host_client->old_colors = host_client->colors; + for (j=0, client = svs.clients ; jactive || !client->spawned) + continue; + MSG_WriteByte (&client->message, svc_updatecolors); + MSG_WriteByte (&client->message, i); + MSG_WriteByte (&client->message, host_client->colors); + } + } + if (host_client->old_frags != host_client->frags) { + host_client->old_frags = host_client->frags; for (j=0, client = svs.clients ; jactive || !client->spawned) continue; MSG_WriteByte (&client->message, svc_updatefrags); MSG_WriteByte (&client->message, i); - MSG_WriteShort (&client->message, sv_player->v->frags); + MSG_WriteShort (&client->message, host_client->frags); } - - host_client->old_frags = sv_player->v->frags; } } - for (j=0, host_client = svs.clients ; jactive) + if (!client->active) continue; - SZ_Write (&host_client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); + SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); } SZ_Clear (&sv.reliable_datagram); @@ -1460,7 +1465,7 @@ void SV_SendNop (client_t *client) MSG_WriteChar (&msg, svc_nop); - if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1) + if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1) SV_DropClient (true); // if the message couldn't send, kick off client->last_message = realtime; } @@ -1483,6 +1488,12 @@ void SV_SendClientMessages (void) if (!host_client->active) continue; + if (host_client->deadsocket) + { + SV_DropClient (true); // if the message couldn't send, kick off + continue; + } + if (host_client->spawned) { if (!SV_SendClientDatagram (host_client)) @@ -1515,14 +1526,14 @@ void SV_SendClientMessages (void) if (host_client->message.cursize || host_client->dropasap) { - if (!NET_CanSendMessage (host_client->netconnection)) + if (!NetConn_CanSendMessage (host_client->netconnection)) continue; if (host_client->dropasap) SV_DropClient (false); // went to another level else { - if (NET_SendMessage (host_client->netconnection, &host_client->message) == -1) + if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->message) == -1) SV_DropClient (true); // if the message couldn't send, kick off SZ_Clear (&host_client->message); host_client->last_message = realtime; @@ -1659,7 +1670,7 @@ void SV_SendReconnect (void) MSG_WriteChar (&msg, svc_stufftext); MSG_WriteString (&msg, "reconnect\n"); - NET_SendToAll (&msg, 5); + NetConn_SendToAll (&msg, 5); if (cls.state != ca_dedicated) Cmd_ExecuteString ("reconnect\n", src_command); @@ -1758,6 +1769,8 @@ void SV_SpawnServer (const char *server) // if (sv.active) SV_SendReconnect (); + else + NetConn_OpenServerPorts(svs.maxclients > 1); // // make cvars consistant @@ -1914,6 +1927,6 @@ void SV_SpawnServer (const char *server) SV_SendServerinfo (host_client); Con_DPrintf ("Server spawned.\n"); - NET_Heartbeat (2); + NetConn_Heartbeat (2); } diff --git a/sv_user.c b/sv_user.c index 1e4b6558..2d1b5dd9 100644 --- a/sv_user.c +++ b/sv_user.c @@ -517,106 +517,95 @@ void SV_ReadClientMove (usercmd_t *move) /* =================== SV_ReadClientMessage - -Returns false if the client should be killed =================== */ -extern void SV_SendServerinfo (client_t *client); -qboolean SV_ReadClientMessage (void) +extern void SV_SendServerinfo(client_t *client); +void SV_ReadClientMessage(void) { - int ret; - int cmd; - char *s; + int cmd; + char *s; + + //MSG_BeginReading (); - for (;;) + for(;;) { -nextmsg: - ret = NET_GetMessage (host_client->netconnection); - if (ret == -1) + if (!host_client->active) { - Con_Printf ("SV_ReadClientMessage: NET_GetMessage failed\n"); - return false; + // a command caused an error + SV_DropClient (false); + return; } - if (!ret) - return true; - MSG_BeginReading (); + if (msg_badread) + { + Con_Printf ("SV_ReadClientMessage: badread\n"); + SV_DropClient (false); + return; + } - for(;;) + cmd = MSG_ReadChar (); + if (cmd == -1) { - if (!host_client->active) - // a command caused an error - return false; + // end of message + break; + } - if (msg_badread) - { - Con_Printf ("SV_ReadClientMessage: badread\n"); - return false; - } + switch (cmd) + { + default: + Con_Printf ("SV_ReadClientMessage: unknown command char %i\n", cmd); + SV_DropClient (false); + return; - cmd = MSG_ReadChar (); + case clc_nop: + break; - switch (cmd) + case clc_stringcmd: + s = MSG_ReadString (); + if (strncasecmp(s, "spawn", 5) == 0 + || strncasecmp(s, "begin", 5) == 0 + || strncasecmp(s, "prespawn", 8) == 0) + Cmd_ExecuteString (s, src_client); + else if (SV_ParseClientCommandQC) { - case -1: - // end of message - goto nextmsg; - - default: - Con_Printf ("SV_ReadClientMessage: unknown command char %i\n", cmd); - return false; - - case clc_nop: - break; - - case clc_stringcmd: - s = MSG_ReadString (); - if (strncasecmp(s, "spawn", 5) == 0 - || strncasecmp(s, "begin", 5) == 0 - || strncasecmp(s, "prespawn", 8) == 0) - Cmd_ExecuteString (s, src_client); - else if (SV_ParseClientCommandQC) - { - G_INT(OFS_PARM0) = PR_SetString(s); - pr_global_struct->self = EDICT_TO_PROG(host_client->edict); - PR_ExecuteProgram ((func_t)(SV_ParseClientCommandQC - pr_functions), ""); - } - else if (strncasecmp(s, "status", 6) == 0 - || strncasecmp(s, "name", 4) == 0 - || strncasecmp(s, "say", 3) == 0 - || strncasecmp(s, "say_team", 8) == 0 - || strncasecmp(s, "tell", 4) == 0 - || strncasecmp(s, "color", 5) == 0 - || strncasecmp(s, "kill", 4) == 0 - || strncasecmp(s, "pause", 5) == 0 - || strncasecmp(s, "kick", 4) == 0 - || strncasecmp(s, "ping", 4) == 0 - || strncasecmp(s, "ban", 3) == 0 - || strncasecmp(s, "pmodel", 6) == 0 - || (gamemode == GAME_NEHAHRA && (strncasecmp(s, "max", 3) == 0 || strncasecmp(s, "monster", 7) == 0 || strncasecmp(s, "scrag", 5) == 0 || strncasecmp(s, "gimme", 5) == 0 || strncasecmp(s, "wraith", 6) == 0)) - || (gamemode != GAME_NEHAHRA && (strncasecmp(s, "god", 3) == 0 || strncasecmp(s, "notarget", 8) == 0 || strncasecmp(s, "fly", 3) == 0 || strncasecmp(s, "give", 4) == 0 || strncasecmp(s, "noclip", 6) == 0))) - Cmd_ExecuteString (s, src_client); - else - Con_Printf("%s tried to %s\n", host_client->name, s); - break; - - case clc_disconnect: - return false; - - case clc_move: - SV_ReadClientMove (&host_client->cmd); - break; - - case clc_ackentities: - EntityFrame_AckFrame(&host_client->entitydatabase, MSG_ReadLong()); - break; + G_INT(OFS_PARM0) = PR_SetString(s); + pr_global_struct->self = EDICT_TO_PROG(host_client->edict); + PR_ExecuteProgram ((func_t)(SV_ParseClientCommandQC - pr_functions), ""); } + else if (strncasecmp(s, "status", 6) == 0 + || strncasecmp(s, "name", 4) == 0 + || strncasecmp(s, "say", 3) == 0 + || strncasecmp(s, "say_team", 8) == 0 + || strncasecmp(s, "tell", 4) == 0 + || strncasecmp(s, "color", 5) == 0 + || strncasecmp(s, "kill", 4) == 0 + || strncasecmp(s, "pause", 5) == 0 + || strncasecmp(s, "kick", 4) == 0 + || strncasecmp(s, "ping", 4) == 0 + || strncasecmp(s, "ban", 3) == 0 + || strncasecmp(s, "pmodel", 6) == 0 + || (gamemode == GAME_NEHAHRA && (strncasecmp(s, "max", 3) == 0 || strncasecmp(s, "monster", 7) == 0 || strncasecmp(s, "scrag", 5) == 0 || strncasecmp(s, "gimme", 5) == 0 || strncasecmp(s, "wraith", 6) == 0)) + || (gamemode != GAME_NEHAHRA && (strncasecmp(s, "god", 3) == 0 || strncasecmp(s, "notarget", 8) == 0 || strncasecmp(s, "fly", 3) == 0 || strncasecmp(s, "give", 4) == 0 || strncasecmp(s, "noclip", 6) == 0))) + Cmd_ExecuteString (s, src_client); + else + Con_Printf("%s tried to %s\n", host_client->name, s); + break; + + case clc_disconnect: + SV_DropClient (false); // client wants to disconnect + return; + + case clc_move: + SV_ReadClientMove (&host_client->cmd); + break; + + case clc_ackentities: + EntityFrame_AckFrame(&host_client->entitydatabase, MSG_ReadLong()); + break; } } - return true; } - /* ================== SV_RunClients @@ -633,12 +622,6 @@ void SV_RunClients (void) sv_player = host_client->edict; - if (!SV_ReadClientMessage ()) - { - SV_DropClient (false); // client misbehaved... - continue; - } - if (!host_client->spawned) { // clear client movement until a new packet is received