This is the network rewrite I've been working on for over a week; multiplayer should...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 22 Jun 2003 09:58:55 +0000 (09:58 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 22 Jun 2003 09:58:55 +0000 (09:58 +0000)
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

33 files changed:
cl_demo.c
cl_input.c
cl_main.c
cl_parse.c
cl_screen.c
client.h
common.c
common.h
host.c
host_cmd.c
makefile
menu.c
menu.h
model_shared.c
model_shared.h
net.h [deleted file]
net_bsd.c [deleted file]
net_dgrm.c [deleted file]
net_dgrm.h [deleted file]
net_loop.c [deleted file]
net_loop.h [deleted file]
net_main.c [deleted file]
net_master.c [deleted file]
net_master.h [deleted file]
net_udp.c [deleted file]
net_udp.h [deleted file]
pr_cmds.c
pr_edict.c
progs.h
quakedef.h
server.h
sv_main.c
sv_user.c

index 5f7ad08..468cdc6 100644 (file)
--- 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();
 }
 
 
index 018eb2c..f92087c 100644 (file)
@@ -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();
        }
 }
 
index cdd48ba..d1b514c 100644 (file)
--- 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);
index 9f11a47..160a7bb 100644 (file)
@@ -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);
index 11bf550..8d3babe 100644 (file)
@@ -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);
 }
 
 /*
index 38402f6..a763403 100644 (file)
--- 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
index 875c8d3..ab20b2c 100644 (file)
--- 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;
+               }
+       }
+}
+
index 80e7c17..8a52aba 100644 (file)
--- 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 93b5501..1c8a00a 100644 (file)
--- 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 ; i<svs.maxclients ; i++)
                if (svs.clients[i].active && svs.clients[i].spawned)
                {
-                       MSG_WriteByte (&svs.clients[i].message, svc_print);
-                       MSG_WriteString (&svs.clients[i].message, string);
+                       MSG_WriteByte(&svs.clients[i].message, svc_print);
+                       MSG_WriteString(&svs.clients[i].message, string);
                }
 
        if (sv_echobprint.integer && cls.state == ca_dedicated)
-               Sys_Printf ("%s", string);
+               Sys_Printf("%s", string);
 }
 
 /*
@@ -390,17 +387,17 @@ Host_ClientCommands
 Send text over to the client to be executed
 =================
 */
-void Host_ClientCommands (const char *fmt, ...)
+void Host_ClientCommands(const char *fmt, ...)
 {
        va_list argptr;
        char string[1024];
 
-       va_start (argptr,fmt);
-       vsprintf (string, fmt,argptr);
-       va_end (argptr);
+       va_start(argptr,fmt);
+       vsprintf(string, fmt,argptr);
+       va_end(argptr);
 
-       MSG_WriteByte (&host_client->message, 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 ; i<svs.maxclients ; i++, client++)
+       for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
        {
                if (!client->active)
                        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 ; i<svs.maxclients ; i++, host_client++)
                {
                        if (host_client->active && 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 ; i<svs.maxclients ; i++, host_client++)
                if (host_client->active)
                        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)
index 98d3526..9e202d1 100644 (file)
@@ -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 ; j<svs.maxclients ; j++, client++)
        {
                if (!client->active)
                        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 ; i<MAX_LIGHTSTYLES ; i++)
        {
                MSG_WriteByte (&host_client->message, 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);
 }
 
index 8a264c6..ff45aed 100644 (file)
--- 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 f7744e5..18e44fe 100644 (file)
--- 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 2031fb1..e45af43 100644 (file)
--- 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];
 
 //
index fcc3a25..5703e61 100644 (file)
@@ -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;
index 6bec208..dd09ee6 100644 (file)
@@ -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 (file)
index 4a69b87..0000000
--- 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 (file)
index 9b547d8..0000000
--- 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 (file)
index 53ab0bd..0000000
+++ /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 <windows.h>
-#elif defined (NeXT)
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#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 (file)
index ad2bf55..0000000
+++ /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 (file)
index 72d3570..0000000
+++ /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 (file)
index 0938fb9..0000000
+++ /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 (file)
index d002764..0000000
+++ /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<net_numdrivers; net_driverlevel++)
-       {
-               if (net_drivers[net_driverlevel].initialized == false)
-                       continue;
-               dfunc.Listen (listening);
-       }
-}
-
-
-static void MaxPlayers_f (void)
-{
-       int n;
-
-       if (Cmd_Argc () != 2)
-       {
-               Con_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients);
-               return;
-       }
-
-       if (sv.active)
-       {
-               Con_Printf ("maxplayers can not be changed while a server is running.\n");
-               return;
-       }
-
-       n = atoi(Cmd_Argv(1));
-       n = bound(1, n, MAX_SCOREBOARD);
-       if (svs.maxclients != n)
-               Con_Printf ("\"maxplayers\" set to \"%u\"\n", n);
-
-       if ((n == 1) && listening)
-               Cbuf_AddText ("listen 0\n");
-
-       if ((n > 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_driverlevel<net_numdrivers; net_driverlevel++)
-       {
-               if (net_drivers[net_driverlevel].initialized == false)
-                       continue;
-               if (net_driverlevel && listening == false)
-                       continue;
-               ret = dfunc.CheckNewConnections ();
-               if (ret)
-                       return ret;
-       }
-
-       return NULL;
-}
-
-/*
-===================
-NET_Close
-===================
-*/
-void NET_Close (qsocket_t *sock)
-{
-       if (!sock)
-               return;
-
-       if (sock->disconnected)
-               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_driverlevel<net_numdrivers; net_driverlevel++)
-               {
-                       if (net_drivers[net_driverlevel].initialized == false)
-                               continue;
-                       if (net_driverlevel && listening == false)
-                               continue;
-                       dfunc.Heartbeat (host);
-               }
-       }
-}
-
-
-int NET_SendToAll(sizebuf_t *data, int blocktime)
-{
-       double          start;
-       int                     i;
-       int                     count = 0;
-       qbyte           state [MAX_SCOREBOARD];
-
-       for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
-       {
-               state[i] = 2;
-               if (host_client->netconnection && 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_driverlevel<net_numdrivers ; net_driverlevel++)
-               {
-               controlSocket = net_drivers[net_driverlevel].Init();
-               if (controlSocket == -1)
-                       continue;
-               net_drivers[net_driverlevel].initialized = true;
-               net_drivers[net_driverlevel].controlSock = controlSocket;
-               if (listening)
-                       net_drivers[net_driverlevel].Listen (true);
-               }
-
-       if (*my_ipx_address)
-               Con_DPrintf("IPX address %s\n", my_ipx_address);
-       if (*my_tcpip_address)
-               Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
-
-       Master_Init ();
-}
-
-/*
-====================
-NET_Shutdown
-====================
-*/
-
-void NET_Shutdown (void)
-{
-       SetNetTime();
-
-       while (net_activeSockets)
-               NET_Close(net_activeSockets);
-
-//
-// shutdown the drivers
-//
-       for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
-       {
-               if (net_drivers[net_driverlevel].initialized == true)
-               {
-                       net_drivers[net_driverlevel].Shutdown ();
-                       net_drivers[net_driverlevel].initialized = false;
-               }
-       }
-
-       Mem_FreePool(&net_mempool);
-}
-
-
-static PollProcedure *pollProcedureList = NULL;
-
-void NET_Poll(void)
-{
-       PollProcedure *pp;
-
-       if (!configRestored)
-               configRestored = true;
-
-       SetNetTime();
-
-       for (pp = pollProcedureList; pp; pp = pp->next)
-       {
-               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 (file)
index 52f6487..0000000
+++ /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 (file)
index a7c3732..0000000
+++ /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 (file)
index 3dbb895..0000000
--- 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 <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-
-#ifdef __sun__
-#include <sys/filio.h>
-#endif
-
-#ifdef NeXT
-#include <libc.h>
-#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 (file)
index dbd6663..0000000
--- 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
-
index 04843d7..ccbb363 100644 (file)
--- 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);
index 83a780e..4acf10b 100644 (file)
@@ -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 ee5d9e2..5934f45 100644 (file)
--- 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)
 
index a4ae392..bd9ca3c 100644 (file)
@@ -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;
index 363a575..8eb1153 100644 (file)
--- 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);
index 3919ddd..fb0049e 100644 (file)
--- 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 ; i<NUM_SPAWN_PARMS ; i++)
                        client->spawn_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 ; i<svs.maxclients ; i++)
-                       if (!svs.clients[i].active)
-                               break;
-               if (i == svs.maxclients)
-                       Sys_Error ("Host_CheckForNewClients: no free clients");
-
-               svs.clients[i].netconnection = ret;
-               SV_ConnectClient (i);
-
-               net_activeconnections++;
-               NET_Heartbeat (1);
-       }
-}
-
-
-
 /*
 ===============================================================================
 
@@ -1392,7 +1354,7 @@ qboolean SV_SendClientDatagram (client_t *client)
                SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
 
 // send the datagram
-       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
                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 ; i<svs.maxclients ; i++, host_client++)
        {
+               // update the host_client fields we care about according to the entity fields
                sv_player = host_client->edict;
-               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 ; j<svs.maxclients ; j++, client++)
+                       {
+                               if (!client->active || !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 ; j<svs.maxclients ; j++, client++)
+                       {
+                               if (!client->active || !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 ; j<svs.maxclients ; j++, client++)
                        {
                                if (!client->active || !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 ; j<svs.maxclients ; j++, host_client++)
+       for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
        {
-               if (!host_client->active)
+               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);
 }
 
index 1e4b655..2d1b5dd 100644 (file)
--- 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