diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 0e6a9999f7ed3d3d2a1dc37caa9e766f389e12f6..9d27c683bf9cbbcebb78ac536d5fd1f6aa9808fd 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -478,6 +478,7 @@ static boolean CL_SendJoin(void)
 		nodewaiting[servernode]++;
 		if (splitscreen || botingame)
 			nodewaiting[servernode]++;
+		net_playercount = nodewaiting[servernode];
 		return true;
 	}
 	// NET TODO
@@ -1206,8 +1207,6 @@ void CL_Reset(void)
 	multiplayer = false;
 	servernode = 0;
 	server = true;
-	net_nodecount = 1;
-	net_playercount = 1;
 	SV_StopServer();
 	SV_ResetServer();
 
diff --git a/src/d_datawrap.c b/src/d_datawrap.c
index 1db92357cae6fa64d5a25fef0f46ffcd24318ffb..34dcdeb9ff8ad55594be5ec472bb8c3409637ca6 100644
--- a/src/d_datawrap.c
+++ b/src/d_datawrap.c
@@ -25,6 +25,12 @@ static UINT16 ReadUINT16(DataWrap dw)
 	return READUINT16(dw->p);
 }
 
+static INT16 ReadINT16(DataWrap dw)
+{
+	CheckEOF(dw, 2);
+	return READINT16(dw->p);
+}
+
 static char *ReadStringn(DataWrap dw, size_t n)
 {
 	char *string = ZZ_Alloc(n+1);
@@ -50,6 +56,9 @@ DataWrap D_NewDataWrap(const void *data, size_t len, jmp_buf *eofjmp)
 
 	dw->ReadUINT8 = ReadUINT8;
 	dw->ReadUINT16 = ReadUINT16;
+
+	dw->ReadINT16 = ReadINT16;
+
 	dw->ReadStringn = ReadStringn;
 	return dw;
 }
diff --git a/src/d_datawrap.h b/src/d_datawrap.h
index 5e7374de4249c293b89f33be265c57d395fc1455..4baf08f63fe7897ca8c0338c6b2360ddfafb3b69 100644
--- a/src/d_datawrap.h
+++ b/src/d_datawrap.h
@@ -8,6 +8,9 @@ typedef struct DataWrap_s {
 
 	UINT8 (*ReadUINT8)(struct DataWrap_s *);
 	UINT16 (*ReadUINT16)(struct DataWrap_s *);
+
+	INT16 (*ReadINT16)(struct DataWrap_s *);
+
 	char *(*ReadStringn)(struct DataWrap_s *, size_t n);
 } *DataWrap;
 
diff --git a/src/d_enet.c b/src/d_enet.c
index fd3b2b04a4d041a36b49c8e0a13ec53ba1c2bdae..9977ddf007c9f787cd3db3eda88f76f3992a8acb 100644
--- a/src/d_enet.c
+++ b/src/d_enet.c
@@ -20,8 +20,13 @@ boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
 enum {
 	DISCONNECT_UNKNOWN = 0,
 	DISCONNECT_SHUTDOWN,
+	DISCONNECT_FULL,
 
-	CLIENT_JOIN = 0
+	CLIENT_ASKMSINFO = 0,
+	CLIENT_JOIN,
+
+	SERVER_MSINFO = 0,
+	SERVER_MAPINFO
 };
 
 static ENetHost *ServerHost = NULL,
@@ -33,6 +38,8 @@ typedef struct PeerData_s {
 	UINT8 node;
 } PeerData;
 
+static void ServerSendMapInfo(UINT8 node);
+
 boolean Net_GetNetStat(void)
 {
 	// set getbps, sendbps, gamelostpercent, lostpercent, etc.
@@ -51,6 +58,24 @@ static void ServerHandlePacket(UINT8 node, DataWrap data)
 			CONS_Printf("NETWORK: Version mismatch!?\n");
 		char *name = data->ReadStringn(data, MAXPLAYERNAME);
 		CONS_Printf("NETWORK: Player '%s' joining...\n", name);
+		net_playercount++;
+		ServerSendMapInfo(node);
+		break;
+	}
+	default:
+		CONS_Printf("NETWORK: Unknown message type recieved from node %u!\n", node);
+		break;
+	}
+}
+
+static void ClientHandlePacket(UINT8 node, DataWrap data)
+{
+	switch(data->ReadUINT8(data))
+	{
+	case SERVER_MAPINFO:
+	{
+		INT16 mapnum = data->ReadINT16(data);
+		G_InitNew(false, G_BuildMapName(mapnum), true, true);
 		break;
 	}
 	default:
@@ -74,14 +99,27 @@ void Net_AckTicker(void)
 			{
 				CL_Reset();
 				D_StartTitle();
-				if (e.data == DISCONNECT_SHUTDOWN)
+				switch(e.data)
+				{
+				case DISCONNECT_SHUTDOWN:
 					M_StartMessage(M_GetText("Server shut down.\n\nPress ESC\n"), NULL, MM_NOTHING);
-				else
+					break;
+				case DISCONNECT_FULL:
+					M_StartMessage(M_GetText("Server is full.\n\nPress ESC\n"), NULL, MM_NOTHING);
+					break;
+				default:
 					M_StartMessage(M_GetText("Disconnected from server.\n\nPress ESC\n"), NULL, MM_NOTHING);
+					break;
+				}
 			}
 			break;
 
 		case ENET_EVENT_TYPE_RECEIVE:
+			pdata = (PeerData *)e.peer->data;
+			if (setjmp(safety))
+				CONS_Printf("NETWORK: There was an EOF error in a recieved packet from server! len %u\n", e.packet->dataLength);
+			else
+				ClientHandlePacket(pdata->node, D_NewDataWrap(e.packet->data, e.packet->dataLength, &safety));
 			enet_packet_destroy(e.packet);
 			break;
 
@@ -93,18 +131,33 @@ void Net_AckTicker(void)
 		switch (e.type)
 		{
 		case ENET_EVENT_TYPE_CONNECT:
+			// turn away new connections when maxplayers is hit
+			// TODO: wait to see if it's a remote console first or something.
+			if (net_playercount >= cv_maxplayers.value)
+			{
+				CONS_Printf("NETWORK: New connection tossed, server is full.\n");
+				enet_peer_disconnect(e.peer, DISCONNECT_FULL);
+				break;
+			}
+
 			for (i = 0; i < MAXNETNODES && nodeingame[i]; i++)
 				;
 			I_Assert(i < MAXNETNODES); // ENet should not be able to send connect events when nodes are full.
+
+			net_nodecount++;
 			nodeingame[i] = true;
 			nodetopeer[i] = e.peer;
+
 			pdata = ZZ_Alloc(sizeof(*pdata));
 			pdata->node = i;
 			e.peer->data = pdata;
+
 			CONS_Printf("NETWORK: Node %u connected.\n", i);
 			break;
 
 		case ENET_EVENT_TYPE_DISCONNECT:
+			if (!e.peer->data)
+				break;
 			pdata = (PeerData *)e.peer->data;
 			if (!nodeleaving[pdata->node])
 			{
@@ -146,8 +199,6 @@ boolean Net_AllAckReceived(void)
 
 void D_SetDoomcom(void)
 {
-	net_nodecount = 0;
-	net_playercount = 0;
 }
 
 void D_NetOpen(void)
@@ -159,6 +210,8 @@ void D_NetOpen(void)
 
 	servernode = 0;
 	nodeingame[servernode] = true;
+	net_nodecount = 1;
+	net_playercount = 0;
 }
 
 void D_NetConnect(const char *hostname, const char *port)
@@ -219,7 +272,7 @@ void D_CloseConnection(void)
 		UINT8 i, waiting=0;
 		// tell everyone to go away
 		for (i = 0; i < MAXNETNODES; i++)
-			if (nodeingame[i])
+			if (nodeingame[i] && servernode != i)
 			{
 				enet_peer_disconnect(nodetopeer[i], DISCONNECT_SHUTDOWN);
 				waiting++;
@@ -269,10 +322,7 @@ void D_CloseConnection(void)
 	netgame = false;
 	addedtogame = false;
 	servernode = 0;
-}
-
-void Net_UnAcknowledgPacket(INT32 node)
-{
+	net_nodecount = net_playercount = 0;
 }
 
 void Net_CloseConnection(INT32 node)
@@ -283,14 +333,6 @@ void Net_CloseConnection(INT32 node)
 	enet_peer_disconnect(nodetopeer[node], 0);
 }
 
-void Net_SendAcks(INT32 node)
-{
-}
-
-void Net_WaitAllAckReceived(UINT32 timeout)
-{
-}
-
 // Client: Can I play? =3 My name is Player so-and-so!
 void Net_SendJoin(void)
 {
@@ -306,3 +348,16 @@ void Net_SendJoin(void)
 	packet = enet_packet_create(data, buf-data, ENET_PACKET_FLAG_RELIABLE);
 	enet_peer_send(nodetopeer[servernode], 0, packet);
 }
+
+static void ServerSendMapInfo(UINT8 node)
+{
+	ENetPacket *packet;
+	UINT8 data[3];
+	UINT8 *buf = data;
+
+	WRITEUINT8(buf, SERVER_MAPINFO);
+	WRITEINT16(buf, gamemap);
+
+	packet = enet_packet_create(data, buf-data, ENET_PACKET_FLAG_RELIABLE);
+	enet_peer_send(nodetopeer[node], 0, packet);
+}
diff --git a/src/d_enet.h b/src/d_enet.h
index 6d249e52d93bb33cbc1913748966afd0e6b25d38..7a2833834a04c827bf61425a84751d3fc0ab45bb 100644
--- a/src/d_enet.h
+++ b/src/d_enet.h
@@ -15,9 +15,6 @@ void D_SetDoomcom(void);
 void D_SaveBan(void);
 boolean D_CheckNetGame(void);
 void D_CloseConnection(void);
-void Net_UnAcknowledgPacket(INT32 node);
 void Net_CloseConnection(INT32 node);
-void Net_SendAcks(INT32 node);
-void Net_WaitAllAckReceived(UINT32 timeout);
 
 void Net_SendJoin(void);