From d4f153d3ca0b31cacf2ffd8c90b75328bff719d2 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sat, 31 Dec 2016 19:26:33 +0100
Subject: [PATCH] Random changes in the netcode lol

---
 src/d_clisrv.c | 1571 +++++++++++++++++++++++++++---------------------
 src/d_clisrv.h |  119 ++--
 src/d_net.c    |  330 +++++++---
 src/d_net.h    |   18 +-
 src/d_netcmd.c |   29 +
 src/d_netcmd.h |    2 +
 src/d_netfil.c |  383 +++++++-----
 src/d_netfil.h |   22 +-
 8 files changed, 1480 insertions(+), 994 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index c0f81ba32..7eb7f6c3f 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -58,14 +58,14 @@
 // NETWORKING
 //
 // gametic is the tic about to (or currently being) run
-// maketic is the tic that hasn't had control made for it yet
-// server:
+// Server:
+//   maketic is the tic that hasn't had control made for it yet
 //   nettics is the tic for each node
 //   firstticstosend is the lowest value of nettics
-// client:
-//   neededtic is the tic needed by the client for run the game
+// Client:
+//   neededtic is the tic needed by the client to run the game
 //   firstticstosend is used to optimize a condition
-// normally maketic >= gametic > 0
+// Normally maketic >= gametic > 0
 
 #define PREDICTIONQUEUE BACKUPTICS
 #define PREDICTIONMASK (PREDICTIONQUEUE-1)
@@ -185,11 +185,17 @@ static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n)
 
 
 
-// some software don't support largest packet
-// (original sersetup, not exactely, but the probabylity of sending a packet
-// of 512 octet is like 0.1)
+// Some software don't support largest packet
+// (original sersetup, not exactely, but the probability of sending a packet
+// of 512 bytes is like 0.1)
 UINT16 software_MAXPACKETLENGTH;
 
+/** Guesses the value of a tic from its lowest byte and from maketic
+  *
+  * \param low The lowest byte of the tic value
+  * \return The full tic value
+  *
+  */
 tic_t ExpandTics(INT32 low)
 {
 	INT32 delta;
@@ -214,7 +220,7 @@ void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum))
 {
 #ifdef PARANOIA
 	if (id >= MAXNETXCMD)
-		I_Error("command id %d too big", id);
+		I_Error("Command id %d too big", id);
 	if (listnetxcmd[id] != 0)
 		I_Error("Command id %d already used", id);
 #endif
@@ -378,7 +384,7 @@ static void ExtraDataTicker(void)
 					{
 						const UINT8 id = *curpos;
 						curpos++;
-						DEBFILE(va("executing x_cmd %u ply %u ", id, i));
+						DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i));
 						(listnetxcmd[id])(&curpos, i);
 						DEBFILE("done\n");
 					}
@@ -400,8 +406,6 @@ static void ExtraDataTicker(void)
 				}
 			}
 		}
-
-	D_FreeTextcmd(gametic);
 }
 
 static void D_Clearticcmd(tic_t tic)
@@ -1034,20 +1038,20 @@ static INT16 Consistancy(void);
 
 typedef enum
 {
-	cl_searching,
-	cl_downloadfiles,
-	cl_askjoin,
-	cl_waitjoinresponse,
+	CL_SEARCHING,
+	CL_DOWNLOADFILES,
+	CL_ASKJOIN,
+	CL_WAITJOINRESPONSE,
 #ifdef JOININGAME
-	cl_downloadsavegame,
+	CL_DOWNLOADSAVEGAME,
 #endif
-	cl_connected,
-	cl_aborted
+	CL_CONNECTED,
+	CL_ABORTED
 } cl_mode_t;
 
 static void GetPackets(void);
 
-static cl_mode_t cl_mode = cl_searching;
+static cl_mode_t cl_mode = CL_SEARCHING;
 
 // Player name send/load
 
@@ -1100,10 +1104,10 @@ static inline void CL_DrawConnectionStatus(void)
 	M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
 	V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
 
-	if (cl_mode != cl_downloadfiles)
+	if (cl_mode != CL_DOWNLOADFILES)
 	{
 		INT32 i, animtime = ((ccstime / 4) & 15) + 16;
-		UINT8 palstart = (cl_mode == cl_searching) ? 128 : 160;
+		UINT8 palstart = (cl_mode == CL_SEARCHING) ? 128 : 160;
 		// 15 pal entries total.
 		const char *cltext;
 
@@ -1113,7 +1117,7 @@ static inline void CL_DrawConnectionStatus(void)
 		switch (cl_mode)
 		{
 #ifdef JOININGAME
-			case cl_downloadsavegame:
+			case CL_DOWNLOADSAVEGAME:
 				cltext = M_GetText("Downloading game state...");
 				Net_GetNetStat();
 				V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
@@ -1122,8 +1126,8 @@ static inline void CL_DrawConnectionStatus(void)
 					va("%3.1fK/s ", ((double)getbps)/1024));
 				break;
 #endif
-			case cl_askjoin:
-			case cl_waitjoinresponse:
+			case CL_ASKJOIN:
+			case CL_WAITJOINRESPONSE:
 				cltext = M_GetText("Requesting to join...");
 				break;
 			default:
@@ -1157,11 +1161,16 @@ static inline void CL_DrawConnectionStatus(void)
 }
 #endif
 
-//
-// CL_SendJoin
-//
-// send a special packet for declare how many player in local
-// used only in arbitratrenetstart()
+/** Sends a special packet to declare how many players in local
+  * Used only in arbitratrenetstart()
+  * Sends a PT_CLIENTJOIN packet to the server
+  *
+  * \return True if the packet was successfully sent
+  * \todo Improve the description...
+  *       Because to be honest, I have no idea what arbitratrenetstart is...
+  *       Is it even used...?
+  *
+  */
 static boolean CL_SendJoin(void)
 {
 	UINT8 localplayers = 1;
@@ -1296,6 +1305,12 @@ static void SV_SendPlayerInfo(INT32 node)
 	HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS);
 }
 
+/** Sends a PT_SERVERCFG packet
+  *
+  * \param node The destination
+  * \return True if the packet was successfully sent
+  *
+  */
 static boolean SV_SendServerConfig(INT32 node)
 {
 	INT32 i;
@@ -1428,7 +1443,7 @@ static void SV_SendSaveGame(INT32 node)
 		WRITEUINT32(savebuffer, 0);
 	}
 
-	SendRam(node, buffertosend, length, SF_RAM, 0);
+	SV_SendRam(node, buffertosend, length, SF_RAM, 0);
 	save_p = NULL;
 }
 
@@ -1523,7 +1538,7 @@ static void CL_LoadReceivedSavegame(void)
 		{
 			CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl);
 			if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
-				CONS_Printf(M_GetText("ZONE"));
+				CONS_Printf(M_GetText(" ZONE"));
 			if (actnum > 0)
 				CONS_Printf(" %2d", actnum);
 		}
@@ -1679,11 +1694,245 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
 
 #endif // ifndef NONET
 
-// use adaptive send using net_bandwidth and stat.sendbytes
+/** Called by CL_ServerConnectionTicker
+  *
+  * \param viams ???
+  * \param asksent ???
+  * \return False if the connection was aborted
+  * \sa CL_ServerConnectionTicker
+  * \sa CL_ConnectToServer
+  *
+  */
+static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
+{
+	INT32 i;
+
+#ifndef NONET
+	// serverlist is updated by GetPacket function
+	if (serverlistcount > 0)
+	{
+		// this can be a responce to our broadcast request
+		if (servernode == -1 || servernode >= MAXNETNODES)
+		{
+			i = 0;
+			servernode = serverlist[i].node;
+			CONS_Printf(M_GetText("Found, "));
+		}
+		else
+		{
+			i = SL_SearchServer(servernode);
+			if (i < 0)
+				return true;
+		}
+
+		// Quit here rather than downloading files and being refused later.
+		if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
+		{
+			D_QuitNetGame();
+			CL_Reset();
+			D_StartTitle();
+			M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING);
+			return false;
+		}
+
+		if (!server)
+		{
+			D_ParseFileneeded(serverlist[i].info.fileneedednum,
+				serverlist[i].info.fileneeded);
+			CONS_Printf(M_GetText("Checking files...\n"));
+			i = CL_CheckFiles();
+			if (i == 2) // cannot join for some reason
+			{
+				D_QuitNetGame();
+				CL_Reset();
+				D_StartTitle();
+				M_StartMessage(M_GetText(
+					"You have WAD files loaded or have\n"
+					"modified the game in some way, and\n"
+					"your file list does not match\n"
+					"the server's file list.\n"
+					"Please restart SRB2 before connecting.\n\n"
+					"Press ESC\n"
+				), NULL, MM_NOTHING);
+				return false;
+			}
+			else if (i == 1)
+				cl_mode = CL_ASKJOIN;
+			else
+			{
+				// must download something
+				// can we, though?
+				if (!CL_CheckDownloadable()) // nope!
+				{
+					D_QuitNetGame();
+					CL_Reset();
+					D_StartTitle();
+					M_StartMessage(M_GetText(
+						"You cannot connect to this server\n"
+						"because you cannot download the files\n"
+						"that you are missing from the server.\n\n"
+						"See the console or log file for\n"
+						"more details.\n\n"
+						"Press ESC\n"
+					), NULL, MM_NOTHING);
+					return false;
+				}
+				// no problem if can't send packet, we will retry later
+				if (CL_SendRequestFile())
+					cl_mode = CL_DOWNLOADFILES;
+			}
+		}
+		else
+			cl_mode = CL_ASKJOIN; // files need not be checked for the server.
+
+		return true;
+	}
+
+	// Ask the info to the server (askinfo packet)
+	if (*asksent + NEWTICRATE < I_GetTime())
+	{
+		SendAskInfo(servernode, viams);
+		*asksent = I_GetTime();
+	}
+#else
+	(void)viams;
+	// No netgames, so we skip this state.
+	cl_mode = CL_ASKJOIN;
+#endif // ifndef NONET/else
+
+	return true;
+}
+
+/** Called by CL_ConnectToServer
+  *
+  * \param viams ???
+  * \param tmpsave The name of the gamestate file???
+  * \param oldtic Used for knowing when to poll events and redraw
+  * \param asksent ???
+  * \return False if the connection was aborted
+  * \sa CL_ServerConnectionSearchTicker
+  * \sa CL_ConnectToServer
+  *
+  */
+static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic_t *oldtic, tic_t *asksent)
+{
+	boolean waitmore;
+	INT32 i;
+
+	switch (cl_mode)
+	{
+		case CL_SEARCHING:
+			if (!CL_ServerConnectionSearchTicker(viams, asksent))
+				return false;
+			break;
+
+		case CL_DOWNLOADFILES:
+			waitmore = false;
+			for (i = 0; i < fileneedednum; i++)
+				if (fileneeded[i].status == FS_DOWNLOADING
+					|| fileneeded[i].status == FS_REQUESTED)
+				{
+					waitmore = true;
+					break;
+				}
+			if (waitmore)
+				break; // exit the case
+
+			cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now
+
+		case CL_ASKJOIN:
+			CL_LoadServerFiles();
+#ifdef JOININGAME
+			// prepare structures to save the file
+			// WARNING: this can be useless in case of server not in GS_LEVEL
+			// but since the network layer doesn't provide ordered packets...
+			CL_PrepareDownloadSaveGame(tmpsave);
+#endif
+			if (CL_SendJoin())
+				cl_mode = CL_WAITJOINRESPONSE;
+			break;
+
+#ifdef JOININGAME
+		case CL_DOWNLOADSAVEGAME:
+			// At this state, the first (and only) needed file is the gamestate
+			if (fileneeded[0].status == FS_FOUND)
+			{
+				// Gamestate is now handled within CL_LoadReceivedSavegame()
+				CL_LoadReceivedSavegame();
+				cl_mode = CL_CONNECTED;
+			} // don't break case continue to CL_CONNECTED
+			else
+				break;
+#endif
+
+		case CL_WAITJOINRESPONSE:
+		case CL_CONNECTED:
+		default:
+			break;
+
+		// Connection closed by cancel, timeout or refusal.
+		case CL_ABORTED:
+			cl_mode = CL_SEARCHING;
+			return false;
+
+	}
+
+	GetPackets();
+	Net_AckTicker();
+
+	// Call it only once by tic
+	if (*oldtic != I_GetTime())
+	{
+		INT32 key;
+
+		I_OsPolling();
+		key = I_GetKey();
+		if (key == KEY_ESCAPE)
+		{
+			CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
+//				M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
+			D_QuitNetGame();
+			CL_Reset();
+			D_StartTitle();
+			return false;
+		}
+
+		// why are these here? this is for servers, we're a client
+		//if (key == 's' && server)
+		//	doomcom->numnodes = (INT16)pnumnodes;
+		//SV_FileSendTicker();
+		*oldtic = I_GetTime();
+
+#ifdef CLIENT_LOADINGSCREEN
+		if (!server && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)
+		{
+			F_TitleScreenTicker(true);
+			F_TitleScreenDrawer();
+			CL_DrawConnectionStatus();
+			I_UpdateNoVsync(); // page flip or blit buffer
+			if (moviemode)
+				M_SaveFrame();
+		}
+#else
+		CON_Drawer();
+		I_UpdateNoVsync();
+#endif
+	}
+	else
+		I_Sleep();
+
+	return true;
+}
+
+/** Use adaptive send using net_bandwidth and stat.sendbytes
+  *
+  * \param viams ???
+  * \todo Better description...
+  *
+  */
 static void CL_ConnectToServer(boolean viams)
 {
 	INT32 pnumnodes, nodewaited = doomcom->numnodes, i;
-	boolean waitmore;
 	tic_t oldtic;
 #ifndef NONET
 	tic_t asksent;
@@ -1694,14 +1943,14 @@ static void CL_ConnectToServer(boolean viams)
 	sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
 #endif
 
-	cl_mode = cl_searching;
+	cl_mode = CL_SEARCHING;
 
 #ifdef CLIENT_LOADINGSCREEN
 	lastfilenum = 0;
 #endif
 
 #ifdef JOININGAME
-	// don't get a corrupt savegame error because tmpsave already exists
+	// Don't get a corrupt savegame error because tmpsave already exists
 	if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1)
 		I_Error("Can't delete %s\n", tmpsave);
 #endif
@@ -1725,7 +1974,7 @@ static void CL_ConnectToServer(boolean viams)
 	pnumnodes = 1;
 	oldtic = I_GetTime() - 1;
 #ifndef NONET
-	asksent = (tic_t)-TICRATE;
+	asksent = (tic_t) - TICRATE;
 
 	i = SL_SearchServer(servernode);
 
@@ -1752,197 +2001,19 @@ static void CL_ConnectToServer(boolean viams)
 
 	do
 	{
-		switch (cl_mode)
-		{
-			case cl_searching:
-#ifndef NONET
-				// serverlist is updated by GetPacket function
-				if (serverlistcount > 0)
-				{
-					// this can be a responce to our broadcast request
-					if (servernode == -1 || servernode >= MAXNETNODES)
-					{
-						i = 0;
-						servernode = serverlist[i].node;
-						CONS_Printf(M_GetText("Found, "));
-					}
-					else
-					{
-						i = SL_SearchServer(servernode);
-						if (i < 0)
-							break; // the case
-					}
-
-					// Quit here rather than downloading files and being refused later.
-					if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
-					{
-						D_QuitNetGame();
-						CL_Reset();
-						D_StartTitle();
-						M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING);
-						return;
-					}
-
-					if (!server)
-					{
-						D_ParseFileneeded(serverlist[i].info.fileneedednum,
-							serverlist[i].info.fileneeded);
-						CONS_Printf(M_GetText("Checking files...\n"));
-						i = CL_CheckFiles();
-						if (i == 2) // cannot join for some reason
-						{
-							D_QuitNetGame();
-							CL_Reset();
-							D_StartTitle();
-							M_StartMessage(M_GetText(
-								"You have WAD files loaded or have\n"
-								"modified the game in some way, and\n"
-								"your file list does not match\n"
-								"the server's file list.\n"
-								"Please restart SRB2 before connecting.\n\n"
-								"Press ESC\n"
-							), NULL, MM_NOTHING);
-							return;
-						}
-						else if (i == 1)
-							cl_mode = cl_askjoin;
-						else
-						{
-							// must download something
-							// can we, though?
-							if (!CL_CheckDownloadable()) // nope!
-							{
-								D_QuitNetGame();
-								CL_Reset();
-								D_StartTitle();
-								M_StartMessage(M_GetText(
-									"You cannot conect to this server\n"
-									"because you cannot download the files\n"
-									"that you are missing from the server.\n\n"
-									"See the console or log file for\n"
-									"more details.\n\n"
-									"Press ESC\n"
-								), NULL, MM_NOTHING);
-								return;
-							}
-							// no problem if can't send packet, we will retry later
-							if (CL_SendRequestFile())
-								cl_mode = cl_downloadfiles;
-						}
-					}
-					else
-						cl_mode = cl_askjoin; // files need not be checked for the server.
-					break;
-				}
-				// ask the info to the server (askinfo packet)
-				if (asksent + NEWTICRATE < I_GetTime())
-				{
-					SendAskInfo(servernode, viams);
-					asksent = I_GetTime();
-				}
-#else
-				(void)viams;
-				// No netgames, so we skip this state.
-				cl_mode = cl_askjoin;
-#endif // ifndef NONET/else
-				break;
-			case cl_downloadfiles:
-				waitmore = false;
-				for (i = 0; i < fileneedednum; i++)
-					if (fileneeded[i].status == FS_DOWNLOADING
-						|| fileneeded[i].status == FS_REQUESTED)
-					{
-						waitmore = true;
-						break;
-					}
-				if (waitmore)
-					break; // exit the case
-
-				cl_mode = cl_askjoin; // don't break case continue to cljoin request now
-			case cl_askjoin:
-				CL_LoadServerFiles();
-#ifdef JOININGAME
-				// prepare structures to save the file
-				// WARNING: this can be useless in case of server not in GS_LEVEL
-				// but since the network layer doesn't provide ordered packets...
-				CL_PrepareDownloadSaveGame(tmpsave);
-#endif
-				if (CL_SendJoin())
-					cl_mode = cl_waitjoinresponse;
-				break;
-#ifdef JOININGAME
-			case cl_downloadsavegame:
-				if (fileneeded[0].status == FS_FOUND)
-				{
-					// Gamestate is now handled within CL_LoadReceivedSavegame()
-					CL_LoadReceivedSavegame();
-					cl_mode = cl_connected;
-				} // don't break case continue to cl_connected
-				else
-					break;
-#endif
-			case cl_waitjoinresponse:
-			case cl_connected:
-			default:
-				break;
-
-			// Connection closed by cancel, timeout or refusal.
-			case cl_aborted:
-				cl_mode = cl_searching;
-				return;
-		}
-
-		GetPackets();
-		Net_AckTicker();
-
-		// call it only one by tic
-		if (oldtic != I_GetTime())
-		{
-			INT32 key;
-
-			I_OsPolling();
-			key = I_GetKey();
-			if (key == KEY_ESCAPE)
-			{
-				CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
-//				M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
-				D_QuitNetGame();
-				CL_Reset();
-				D_StartTitle();
-				return;
-			}
-
-			// why are these here? this is for servers, we're a client
-			//if (key == 's' && server)
-			//	doomcom->numnodes = (INT16)pnumnodes;
-			//FiletxTicker();
-			oldtic = I_GetTime();
-
-#ifdef CLIENT_LOADINGSCREEN
-			if (!server && cl_mode != cl_connected && cl_mode != cl_aborted)
-			{
-				F_TitleScreenTicker(true);
-				F_TitleScreenDrawer();
-				CL_DrawConnectionStatus();
-				I_UpdateNoVsync(); // page flip or blit buffer
-				if (moviemode)
-					M_SaveFrame();
-			}
-#else
-			CON_Drawer();
-			I_UpdateNoVsync();
-#endif
-		}
-		else I_Sleep();
+		// If the connection was aborted for some reason, leave
+		if (!CL_ServerConnectionTicker(viams, tmpsave, &oldtic, &asksent))
+			return;
 
 		if (server)
 		{
 			pnumnodes = 0;
 			for (i = 0; i < MAXNETNODES; i++)
-				if (nodeingame[i]) pnumnodes++;
+				if (nodeingame[i])
+					pnumnodes++;
 		}
 	}
-	while (!(cl_mode == cl_connected && (!server || (server && nodewaited <= pnumnodes))));
+	while (!(cl_mode == CL_CONNECTED && (!server || (server && nodewaited <= pnumnodes))));
 
 	DEBFILE(va("Synchronisation Finished\n"));
 
@@ -2199,7 +2270,6 @@ void CL_ClearPlayer(INT32 playernum)
 			P_RemoveMobj(players[playernum].mo->tracer);
 		P_RemoveMobj(players[playernum].mo);
 	}
-	players[playernum].mo = NULL;
 	memset(&players[playernum], 0, sizeof (player_t));
 }
 
@@ -2711,6 +2781,11 @@ void D_ClientServerInit(void)
 	COM_AddCommand("reloadbans", Command_ReloadBan);
 	COM_AddCommand("connect", Command_connect);
 	COM_AddCommand("nodes", Command_Nodes);
+#define PACKETDROP
+#ifdef PACKETDROP
+	COM_AddCommand("drop", Command_Drop);
+	COM_AddCommand("droprate", Command_Droprate);
+#endif
 #endif
 
 	RegisterNetXCmd(XD_KICK, Got_KickCmd);
@@ -2754,7 +2829,7 @@ void SV_ResetServer(void)
 
 	// +1 because this command will be executed in com_executebuffer in
 	// tryruntic so gametic will be incremented, anyway maketic > gametic
-	// is not a issue
+	// is not an issue
 
 	maketic = gametic + 1;
 	neededtic = maketic;
@@ -2808,7 +2883,7 @@ static inline void SV_GenContext(void)
 	for (i = 0; i < 8; i++)
 	{
 		const char a = M_RandomKey(26*2);
-		if (a <= 26) // uppercase
+		if (a < 26) // uppercase
 			server_context[i] = 'A'+a;
 		else // lowercase
 			server_context[i] = 'a'+(a-26);
@@ -2843,7 +2918,7 @@ void D_QuitNetGame(void)
 		if (serverrunning && ms_RoomId > 0)
 			UnregisterServer();
 	}
-	else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]!=0)
+	else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode])
 	{
 		netbuffer->packettype = PT_CLIENTQUIT;
 		HSendPacket(servernode, true, 0, 0);
@@ -2864,12 +2939,12 @@ void D_QuitNetGame(void)
 #endif
 }
 
-// add a node to the game (player will follow at map change or at savegame....)
+// Adds a node to the game (player will follow at map change or at savegame....)
 static inline void SV_AddNode(INT32 node)
 {
 	nettics[node] = gametic;
 	supposedtics[node] = gametic;
-	// little hack because the server connect to itself and put
+	// little hack because the server connects to itself and puts
 	// nodeingame when connected not here
 	if (node)
 		nodeingame[node] = true;
@@ -3019,7 +3094,7 @@ static boolean SV_AddWaitingPlayers(void)
 
 void CL_AddSplitscreenPlayer(void)
 {
-	if (cl_mode == cl_connected)
+	if (cl_mode == CL_CONNECTED)
 		CL_SendJoin();
 }
 
@@ -3027,7 +3102,7 @@ void CL_RemoveSplitscreenPlayer(void)
 {
 	XBOXSTATIC UINT8 buf[2];
 
-	if (cl_mode != cl_connected)
+	if (cl_mode != CL_CONNECTED)
 		return;
 
 	buf[0] = (UINT8)secondarydisplayplayer;
@@ -3038,7 +3113,7 @@ void CL_RemoveSplitscreenPlayer(void)
 // is there a game running
 boolean Playing(void)
 {
-	return (server && serverrunning) || (!server && cl_mode == cl_connected);
+	return (server && serverrunning) || (!server && cl_mode == CL_CONNECTED);
 }
 
 boolean SV_SpawnServer(void)
@@ -3086,7 +3161,7 @@ void SV_StopServer(void)
 		D_Clearticcmd(i);
 
 	consoleplayer = 0;
-	cl_mode = cl_searching;
+	cl_mode = CL_SEARCHING;
 	maketic = gametic+1;
 	neededtic = maketic;
 	serverrunning = false;
@@ -3132,6 +3207,11 @@ static size_t TotalTextCmdPerTic(tic_t tic)
 	return total;
 }
 
+/** Called when a PT_CLIENTJOIN packet is received
+  *
+  * \param node The packet sender
+  *
+  */
 static void HandleConnect(SINT8 node)
 {
 	if (bannednode && bannednode[node])
@@ -3163,6 +3243,9 @@ static void HandleConnect(SINT8 node)
 #endif
 			SV_AddNode(node);
 
+			/// \note Wait what???
+			///       What if the gamestate takes more than one second to get downloaded?
+			///       Or if a lagspike happens?
 			// you get a free second before desynch checks. use it wisely.
 			SV_InitResynchVars(node);
 
@@ -3171,6 +3254,7 @@ static void HandleConnect(SINT8 node)
 			if (!SV_SendServerConfig(node))
 			{
 				G_SetGamestate(backupstate);
+				/// \note Shouldn't SV_SendRefuse be called before ResetNode?
 				ResetNode(node);
 				SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again"));
 				/// \todo fix this !!!
@@ -3201,6 +3285,11 @@ static void HandleConnect(SINT8 node)
 	}
 }
 
+/** Called when a PT_SERVERSHUTDOWN packet is received
+  *
+  * \param node The packet sender (should be the server)
+  *
+  */
 static void HandleShutdown(SINT8 node)
 {
 	(void)node;
@@ -3210,6 +3299,11 @@ static void HandleShutdown(SINT8 node)
 	M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING);
 }
 
+/** Called when a PT_NODETIMEOUT packet is received
+  *
+  * \param node The packet sender (should be the server)
+  *
+  */
 static void HandleTimeout(SINT8 node)
 {
 	(void)node;
@@ -3220,6 +3314,12 @@ static void HandleTimeout(SINT8 node)
 }
 
 #ifndef NONET
+/** Called when a PT_SERVERINFO packet is received
+  *
+  * \param node The packet sender
+  * \note What happens if the packet comes from a client or something like that?
+  *
+  */
 static void HandleServerInfo(SINT8 node)
 {
 	// compute ping in ms
@@ -3233,527 +3333,570 @@ static void HandleServerInfo(SINT8 node)
 }
 #endif
 
-/**	\brief GetPackets
+/** Handles a packet received from a node that isn't in game
+  *
+  * \param node The packet sender
+  * \todo Choose a better name, as the packet can also come from the server apparently?
+  * \sa HandlePacketFromPlayer
+  * \sa GetPackets
+  *
+  */
+static void HandlePacketFromAwayNode(SINT8 node)
+{
+	if (node != servernode)
+		DEBFILE(va("Received packet from unknown host %d\n", node));
 
-  \todo  break this 300 line function into multiple functions
-*/
-static void GetPackets(void)
-{FILESTAMP
-	XBOXSTATIC INT32 netconsole;
-	XBOXSTATIC SINT8 node;
-	XBOXSTATIC tic_t realend,realstart;
-	XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak;
-FILESTAMP
+	switch (netbuffer->packettype)
+	{
+		case PT_ASKINFOVIAMS:
+			if (server && serverrunning)
+			{
+				INT32 clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
+				SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
+				SV_SendPlayerInfo(clientnode); // Send extra info
+				Net_CloseConnection(clientnode);
+				// Don't close connection to MS.
+			}
+			break;
 
-	player_joining = false;
+		case PT_ASKINFO:
+			if (server && serverrunning)
+			{
+				SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time));
+				SV_SendPlayerInfo(node); // Send extra info
+				Net_CloseConnection(node);
+			}
+			break;
 
-	while (HGetPacket())
-	{
-		node = (SINT8)doomcom->remotenode;
-		if (netbuffer->packettype == PT_CLIENTJOIN && server)
-		{
-			HandleConnect(node);
-			continue;
-		}
-		if (netbuffer->packettype == PT_SERVERSHUTDOWN && node == servernode
-			&& !server && cl_mode != cl_searching)
-		{
-			HandleShutdown(node);
-			continue;
-		}
-		if (netbuffer->packettype == PT_NODETIMEOUT && node == servernode
-			&& !server && cl_mode != cl_searching)
-		{
-			HandleTimeout(node);
-			continue;
-		}
+		case PT_SERVERREFUSE: // Negative response of client join request
+			if (server && serverrunning)
+			{ // But wait I thought I'm the server?
+				Net_CloseConnection(node);
+				break;
+			}
+			if (cl_mode == CL_WAITJOINRESPONSE)
+			{
+				D_QuitNetGame();
+				CL_Reset();
+				D_StartTitle();
 
-#ifndef NONET
-		if (netbuffer->packettype == PT_SERVERINFO)
-		{
-			HandleServerInfo(node);
-			continue;
-		}
-#endif
+				M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
+					netbuffer->u.serverrefuse.reason), NULL, MM_NOTHING);
 
-		if (netbuffer->packettype == PT_PLAYERINFO)
-			continue; // We do nothing with PLAYERINFO, that's for the MS browser.
+				// Will be reset by caller. Signals refusal.
+				cl_mode = CL_ABORTED;
+			}
+			break;
 
-		if (!nodeingame[node])
+		case PT_SERVERCFG: // Positive response of client join request
 		{
-			if (node != servernode)
-				DEBFILE(va("Received packet from unknown host %d\n", node));
+			INT32 j;
+			UINT8 *scp;
+
+			if (server && serverrunning && node != servernode)
+			{ // but wait I thought I'm the server?
+				Net_CloseConnection(node);
+				break;
+			}
+			/// \note how would this happen? and is it doing the right thing if it does?
+			if (cl_mode != CL_WAITJOINRESPONSE)
+				break;
 
-			// anyone trying to join
-			switch (netbuffer->packettype)
+			if (!server)
 			{
-				case PT_ASKINFOVIAMS:
-					if (server && serverrunning)
-					{
-						INT32 clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
-						SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
-						SV_SendPlayerInfo(clientnode); // send extra info
-						Net_CloseConnection(clientnode);
-						// Don't close connection to MS.
-					}
-					break;
+				maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
+				gametype = netbuffer->u.servercfg.gametype;
+				modifiedgame = netbuffer->u.servercfg.modifiedgame;
+				adminplayer = netbuffer->u.servercfg.adminplayer;
+				memcpy(server_context, netbuffer->u.servercfg.server_context, 8);
+			}
 
-				case PT_ASKINFO:
-					if (server && serverrunning)
-					{
-						SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time));
-						SV_SendPlayerInfo(node); // send extra info
-						Net_CloseConnection(node);
-					}
-					break;
-				case PT_SERVERREFUSE: // negative response of client join request
-					if (server && serverrunning)
-					{ // but wait I thought I'm the server?
-						Net_CloseConnection(node);
-						break;
-					}
-					if (cl_mode == cl_waitjoinresponse)
-					{
-						D_QuitNetGame();
-						CL_Reset();
-						D_StartTitle();
-
-						M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
-							netbuffer->u.serverrefuse.reason), NULL, MM_NOTHING);
-
-						// Will be reset by caller. Signals refusal.
-						cl_mode = cl_aborted;
-					}
-					break;
-				case PT_SERVERCFG: // positive response of client join request
-				{
-					INT32 j;
-					UINT8 *scp;
-
-					if (server && serverrunning && node != servernode)
-					{ // but wait I thought I'm the server?
-						Net_CloseConnection(node);
-						break;
-					}
-					/// \note how would this happen? and is it doing the right thing if it does?
-					if (cl_mode != cl_waitjoinresponse)
-						break;
-
-					if (!server)
-					{
-						maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
-						gametype = netbuffer->u.servercfg.gametype;
-						modifiedgame = netbuffer->u.servercfg.modifiedgame;
-						adminplayer = netbuffer->u.servercfg.adminplayer;
-						memcpy(server_context, netbuffer->u.servercfg.server_context, 8);
-					}
+			nodeingame[(UINT8)servernode] = true;
+			serverplayer = netbuffer->u.servercfg.serverplayer;
+			doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum);
+			mynode = netbuffer->u.servercfg.clientnode;
+			if (serverplayer >= 0)
+				playernode[(UINT8)serverplayer] = servernode;
 
-					nodeingame[(UINT8)servernode] = true;
-					serverplayer = netbuffer->u.servercfg.serverplayer;
-					doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum);
-					mynode = netbuffer->u.servercfg.clientnode;
-					if (serverplayer >= 0)
-						playernode[(UINT8)serverplayer] = servernode;
-
-					if (netgame)
+			if (netgame)
 #ifdef JOININGAME
-						CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n"));
+				CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n"));
 #else
-						CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n"));
+				CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n"));
 #endif
-					DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode));
+			DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode));
 
-					memset(playeringame, 0, sizeof(playeringame));
-					for (j = 0; j < MAXPLAYERS; j++)
-					{
-						if (netbuffer->u.servercfg.playerskins[j] == 0xFF
-						 && netbuffer->u.servercfg.playercolor[j] == 0xFF)
-							continue; // not in game
+			memset(playeringame, 0, sizeof(playeringame));
+			for (j = 0; j < MAXPLAYERS; j++)
+			{
+				if (netbuffer->u.servercfg.playerskins[j] == 0xFF
+				 && netbuffer->u.servercfg.playercolor[j] == 0xFF)
+					continue; // not in game
 
-						playeringame[j] = true;
-						SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]);
-						players[j].skincolor = netbuffer->u.servercfg.playercolor[j];
-					}
+				playeringame[j] = true;
+				SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]);
+				players[j].skincolor = netbuffer->u.servercfg.playercolor[j];
+			}
 
-					scp = netbuffer->u.servercfg.varlengthinputs;
-					CV_LoadPlayerNames(&scp);
-					CV_LoadNetVars(&scp);
+			scp = netbuffer->u.servercfg.varlengthinputs;
+			CV_LoadPlayerNames(&scp);
+			CV_LoadNetVars(&scp);
 #ifdef JOININGAME
-					if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* ||
-						netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/)
-						cl_mode = cl_downloadsavegame;
-					else
+			/// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook?
+			///       Shouldn't them be downloaded even at intermission time?
+			///       Also, according to HandleConnect, the server will send the savegame even during intermission...
+			if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* ||
+				netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/)
+				cl_mode = CL_DOWNLOADSAVEGAME;
+			else
 #endif
-						cl_mode = cl_connected;
-					break;
-				}
-				// handled in d_netfil.c
-				case PT_FILEFRAGMENT:
-					if (server)
-					{ // but wait I thought I'm the server?
-						Net_CloseConnection(node);
-						break;
-					}
-					else
-						Got_Filetxpak();
-					break;
-				case PT_REQUESTFILE:
-					if (server)
-						Got_RequestFilePak(node);
-					break;
-				case PT_NODETIMEOUT:
-				case PT_CLIENTQUIT:
-					if (server)
-						Net_CloseConnection(node);
-					break;
-				case PT_CLIENTCMD:
-					break; // this is not an "unknown packet"
-				case PT_SERVERTICS:
-					// do not remove my own server (we have just get a out of order packet)
-					if (node == servernode)
-						break;
-				default:
-					DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype));
-					Net_CloseConnection(node);
-					break; // ignore it
-			} // switch
-			continue; //while
+				cl_mode = CL_CONNECTED;
+			break;
 		}
-		if (dedicated && node == 0) netconsole = 0;
-		else netconsole = nodetoplayer[node];
+
+		// Handled in d_netfil.c
+		case PT_FILEFRAGMENT:
+			if (server)
+			{ // But wait I thought I'm the server?
+				Net_CloseConnection(node);
+				break;
+			}
+			else
+				Got_Filetxpak();
+			break;
+
+		case PT_REQUESTFILE:
+			if (server)
+				Got_RequestFilePak(node);
+			break;
+
+		case PT_NODETIMEOUT:
+		case PT_CLIENTQUIT:
+			if (server)
+				Net_CloseConnection(node);
+			break;
+
+		case PT_CLIENTCMD:
+			break; // This is not an "unknown packet"
+
+		case PT_SERVERTICS:
+			// Do not remove my own server (we have just get a out of order packet)
+			if (node == servernode)
+				break;
+
+		default:
+			DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype));
+			Net_CloseConnection(node);
+			break; // Ignore it
+
+	}
+}
+
+/** Handles a packet received from a node that is in game
+  *
+  * \param node The packet sender
+  * \todo Choose a better name
+  * \sa HandlePacketFromAwayNode
+  * \sa GetPackets
+  *
+  */
+void HandlePacketFromPlayer(SINT8 node)
+{FILESTAMP
+	XBOXSTATIC INT32 netconsole;
+	XBOXSTATIC tic_t realend, realstart;
+	XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak;
+FILESTAMP
+
+	txtpak = NULL;
+
+	if (dedicated && node == 0)
+		netconsole = 0;
+	else
+		netconsole = nodetoplayer[node];
 #ifdef PARANOIA
-		if (netconsole >= MAXPLAYERS)
-			I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole);
+	if (netconsole >= MAXPLAYERS)
+		I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole);
 #endif
 
-		txtpak = NULL;
-
-		switch (netbuffer->packettype)
-		{
+	switch (netbuffer->packettype)
+	{
 // -------------------------------------------- SERVER RECEIVE ----------
-			case PT_RESYNCHGET:
-				SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot);
+		case PT_RESYNCHGET:
+			SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot);
+			break;
+		case PT_CLIENTCMD:
+		case PT_CLIENT2CMD:
+		case PT_CLIENTMIS:
+		case PT_CLIENT2MIS:
+		case PT_NODEKEEPALIVE:
+		case PT_NODEKEEPALIVEMIS:
+			if (!server)
 				break;
-			case PT_CLIENTCMD:
-			case PT_CLIENT2CMD:
-			case PT_CLIENTMIS:
-			case PT_CLIENT2MIS:
-			case PT_NODEKEEPALIVE:
-			case PT_NODEKEEPALIVEMIS:
-				if (!server)
-					break;
 
-				// ignore tics from those not synched
-				if (resynch_inprogress[node])
-					break;
+			// Ignore tics from those not synched
+			if (resynch_inprogress[node])
+				break;
 
-				// to save bytes, only the low byte of tic numbers are sent
-				// Figure out what the rest of the bytes are
-				realstart = ExpandTics(netbuffer->u.clientpak.client_tic);
-				realend = ExpandTics(netbuffer->u.clientpak.resendfrom);
+			// To save bytes, only the low byte of tic numbers are sent
+			// Use ExpandTics to figure out what the rest of the bytes are
+			realstart = ExpandTics(netbuffer->u.clientpak.client_tic);
+			realend = ExpandTics(netbuffer->u.clientpak.resendfrom);
 
-				if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
-					|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
-					|| supposedtics[node] < realend)
-				{
-					supposedtics[node] = realend;
-				}
-				// discard out of order packet
-				if (nettics[node] > realend)
-				{
-					DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node]));
-					break;
-				}
+			if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
+				|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
+				|| supposedtics[node] < realend)
+			{
+				supposedtics[node] = realend;
+			}
+			// Discard out of order packet
+			if (nettics[node] > realend)
+			{
+				DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node]));
+				break;
+			}
 
-				// update the nettics
-				nettics[node] = realend;
+			// Update the nettics
+			nettics[node] = realend;
 
-				// don't do anything for packets of type NODEKEEPALIVE?
-				if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE
-					|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
-					break;
+			// Don't do anything for packets of type NODEKEEPALIVE?
+			if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE
+				|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
+				break;
 
-				// copy ticcmd
-				G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1);
+			// Copy ticcmd
+			G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1);
 
-				// check ticcmd for "speed hacks"
-				if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE
-					|| netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE)
-				{
-					XBOXSTATIC char buf[2];
-					CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value recieved from node %d\n"), netconsole);
-					//D_Clearticcmd(k);
+			// Check ticcmd for "speed hacks"
+			if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE
+				|| netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE)
+			{
+				XBOXSTATIC char buf[2];
+				CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole);
+				//D_Clearticcmd(k);
 
-					buf[0] = (char)netconsole;
-					buf[1] = KICK_MSG_CON_FAIL;
-					SendNetXCmd(XD_KICK, &buf, 2);
-					break;
-				}
+				buf[0] = (char)netconsole;
+				buf[1] = KICK_MSG_CON_FAIL;
+				SendNetXCmd(XD_KICK, &buf, 2);
+				break;
+			}
 
-				// splitscreen cmd
-				if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0)
-					G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
-						&netbuffer->u.client2pak.cmd2, 1);
+			// Splitscreen cmd
+			if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0)
+				G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
+					&netbuffer->u.client2pak.cmd2, 1);
 
-				// a delay before we check resynching
-				// used on join or just after a synch fail
-				if (resynch_delay[node])
+			// A delay before we check resynching
+			// Used on join or just after a synch fail
+			if (resynch_delay[node])
+			{
+				--resynch_delay[node];
+				break;
+			}
+			// Check player consistancy during the level
+			if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL
+				&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy))
+			{
+				SV_RequireResynch(node);
+
+				if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250)
 				{
-					--resynch_delay[node];
+					if (cv_blamecfail.value)
+						CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
+							netconsole+1, player_names[netconsole],
+							consistancy[realstart%BACKUPTICS],
+							SHORT(netbuffer->u.clientpak.consistancy));
+					DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
+						netconsole, realstart, consistancy[realstart%BACKUPTICS],
+						SHORT(netbuffer->u.clientpak.consistancy)));
 					break;
 				}
-				// check player consistancy during the level
-				if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL
-					&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy))
+				else
 				{
-					SV_RequireResynch(node);
+					XBOXSTATIC UINT8 buf[3];
 
-					if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250)
-					{
-						if (cv_blamecfail.value)
-							CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
-								netconsole+1, player_names[netconsole],
-								consistancy[realstart%BACKUPTICS],
-								SHORT(netbuffer->u.clientpak.consistancy));
-						DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
-							netconsole, realstart, consistancy[realstart%BACKUPTICS],
-							SHORT(netbuffer->u.clientpak.consistancy)));
-						break;
-					}
-					else
-					{
-						XBOXSTATIC UINT8 buf[3];
-
-						buf[0] = (UINT8)netconsole;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-						DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
-							netconsole, realstart, consistancy[realstart%BACKUPTICS],
-							SHORT(netbuffer->u.clientpak.consistancy)));
-						break;
-					}
+					buf[0] = (UINT8)netconsole;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
+					DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
+						netconsole, realstart, consistancy[realstart%BACKUPTICS],
+						SHORT(netbuffer->u.clientpak.consistancy)));
+					break;
 				}
-				else if (resynch_score[node])
-					--resynch_score[node];
+			}
+			else if (resynch_score[node])
+				--resynch_score[node];
+			break;
+		case PT_TEXTCMD2: // splitscreen special
+			netconsole = nodetoplayer2[node];
+		case PT_TEXTCMD:
+			if (!server)
 				break;
-			case PT_TEXTCMD2: // splitscreen special
-				netconsole = nodetoplayer2[node];
-			case PT_TEXTCMD:
-				if (!server)
-					break;
 
-				if (netconsole < 0 || netconsole >= MAXPLAYERS)
-					Net_UnAcknowledgPacket(node);
-				else
+			if (netconsole < 0 || netconsole >= MAXPLAYERS)
+				Net_UnAcknowledgePacket(node);
+			else
+			{
+				size_t j;
+				tic_t tic = maketic;
+				UINT8 *textcmd;
+
+				// check if tic that we are making isn't too large else we cannot send it :(
+				// doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time
+				j = software_MAXPACKETLENGTH
+					- (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE
+					+ (doomcom->numslots+1)*sizeof(ticcmd_t));
+
+				// search a tic that have enougth space in the ticcmd
+				while ((textcmd = D_GetExistingTextcmd(tic, netconsole)),
+					(TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD)
+					&& tic < firstticstosend + BACKUPTICS)
+					tic++;
+
+				if (tic >= firstticstosend + BACKUPTICS)
 				{
-					size_t j;
-					tic_t tic = maketic;
-					UINT8 *textcmd;
-
-					// check if tic that we are making isn't too large else we cannot send it :(
-					// doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time
-					j = software_MAXPACKETLENGTH
-						- (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE
-						+ (doomcom->numslots+1)*sizeof(ticcmd_t));
-
-					// search a tic that have enougth space in the ticcmd
-					while ((textcmd = D_GetExistingTextcmd(tic, netconsole)),
-						(TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD)
-						&& tic < firstticstosend + BACKUPTICS)
-						tic++;
-
-					if (tic >= firstticstosend + BACKUPTICS)
-					{
-						DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, "
-							"tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)),
-							maketic, firstticstosend, node, netconsole));
-						Net_UnAcknowledgPacket(node);
-						break;
-					}
+					DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, "
+						"tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)),
+						maketic, firstticstosend, node, netconsole));
+					Net_UnAcknowledgePacket(node);
+					break;
+				}
 
-					// Make sure we have a buffer
-					if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole);
+				// Make sure we have a buffer
+				if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole);
 
-					DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n",
-						tic, textcmd[0]+1, netconsole, firstticstosend, maketic));
+				DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n",
+					tic, textcmd[0]+1, netconsole, firstticstosend, maketic));
 
-					M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]);
-					textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
-				}
+				M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]);
+				textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
+			}
+			break;
+		case PT_NODETIMEOUT:
+		case PT_CLIENTQUIT:
+			if (!server)
 				break;
-			case PT_NODETIMEOUT:
-			case PT_CLIENTQUIT:
-				if (!server)
-					break;
 
-				// nodeingame will be put false in the execution of kick command
-				// this allow to send some packets to the quitting client to have their ack back
-				nodewaiting[node] = 0;
-				if (netconsole != -1 && playeringame[netconsole])
+			// nodeingame will be put false in the execution of kick command
+			// this allow to send some packets to the quitting client to have their ack back
+			nodewaiting[node] = 0;
+			if (netconsole != -1 && playeringame[netconsole])
+			{
+				XBOXSTATIC UINT8 buf[2];
+				buf[0] = (UINT8)netconsole;
+				if (netbuffer->packettype == PT_NODETIMEOUT)
+					buf[1] = KICK_MSG_TIMEOUT;
+				else
+					buf[1] = KICK_MSG_PLAYER_QUIT;
+				SendNetXCmd(XD_KICK, &buf, 2);
+				nodetoplayer[node] = -1;
+				if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
+					&& playeringame[(UINT8)nodetoplayer2[node]])
 				{
-					XBOXSTATIC UINT8 buf[2];
-					buf[0] = (UINT8)netconsole;
-					if (netbuffer->packettype == PT_NODETIMEOUT)
-						buf[1] = KICK_MSG_TIMEOUT;
-					else
-						buf[1] = KICK_MSG_PLAYER_QUIT;
+					buf[0] = nodetoplayer2[node];
 					SendNetXCmd(XD_KICK, &buf, 2);
-					nodetoplayer[node] = -1;
-					if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
-						&& playeringame[(UINT8)nodetoplayer2[node]])
-					{
-						buf[0] = nodetoplayer2[node];
-						SendNetXCmd(XD_KICK, &buf, 2);
-						nodetoplayer2[node] = -1;
-					}
+					nodetoplayer2[node] = -1;
 				}
-				Net_CloseConnection(node);
-				nodeingame[node] = false;
-				break;
+			}
+			Net_CloseConnection(node);
+			nodeingame[node] = false;
+			break;
 // -------------------------------------------- CLIENT RECEIVE ----------
-			case PT_RESYNCHEND:
-				// Only accept PT_RESYNCHEND from the server.
-				if (node != servernode)
+		case PT_RESYNCHEND:
+			// Only accept PT_RESYNCHEND from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHEND", node);
+
+				if (server)
 				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHEND", node);
+					XBOXSTATIC UINT8 buf[2];
+					buf[0] = (UINT8)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
+				}
 
-					if (server)
-					{
-						XBOXSTATIC UINT8 buf[2];
-						buf[0] = (UINT8)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
+				break;
+			}
+			resynch_local_inprogress = false;
 
-					break;
-				}
-				resynch_local_inprogress = false;
+			P_SetRandSeed(netbuffer->u.resynchend.randomseed);
 
-				P_SetRandSeed(netbuffer->u.resynchend.randomseed);
+			if (gametype == GT_CTF)
+				resynch_read_ctf(&netbuffer->u.resynchend);
+			resynch_read_others(&netbuffer->u.resynchend);
 
-				if (gametype == GT_CTF)
-					resynch_read_ctf(&netbuffer->u.resynchend);
-				resynch_read_others(&netbuffer->u.resynchend);
+			break;
+		case PT_SERVERTICS:
+			// Only accept PT_SERVERTICS from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node);
 
-				break;
-			case PT_SERVERTICS:
-				// Only accept PT_SERVERTICS from the server.
-				if (node != servernode)
+				if (server)
 				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_SERVERTICS", node);
+					XBOXSTATIC UINT8 buf[2];
+					buf[0] = (UINT8)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
+				}
 
-					if (server)
-					{
-						XBOXSTATIC UINT8 buf[2];
-						buf[0] = (UINT8)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
+				break;
+			}
 
-					break;
-				}
+			realstart = ExpandTics(netbuffer->u.serverpak.starttic);
+			realend = realstart + netbuffer->u.serverpak.numtics;
 
-				realstart = ExpandTics(netbuffer->u.serverpak.starttic);
-				realend = realstart + netbuffer->u.serverpak.numtics;
+			if (!txtpak)
+				txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots
+					* netbuffer->u.serverpak.numtics];
 
-				if (!txtpak)
-					txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots
-						* netbuffer->u.serverpak.numtics];
+			if (realend > gametic + BACKUPTICS)
+				realend = gametic + BACKUPTICS;
+			cl_packetmissed = realstart > neededtic;
 
-				if (realend > gametic + BACKUPTICS)
-					realend = gametic + BACKUPTICS;
-				cl_packetmissed = realstart > neededtic;
+			if (realstart <= neededtic && realend > neededtic)
+			{
+				tic_t i, j;
+				pak = (UINT8 *)&netbuffer->u.serverpak.cmds;
 
-				if (realstart <= neededtic && realend > neededtic)
+				for (i = realstart; i < realend; i++)
 				{
-					tic_t i, j;
-					pak = (UINT8 *)&netbuffer->u.serverpak.cmds;
-
-					for (i = realstart; i < realend; i++)
-					{
-						// clear first
-						D_Clearticcmd(i);
+					// clear first
+					D_Clearticcmd(i);
 
-						// copy the tics
-						pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak,
-							netbuffer->u.serverpak.numslots*sizeof (ticcmd_t));
+					// copy the tics
+					pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak,
+						netbuffer->u.serverpak.numslots*sizeof (ticcmd_t));
 
-						// copy the textcmds
-						numtxtpak = *txtpak++;
-						for (j = 0; j < numtxtpak; j++)
-						{
-							INT32 k = *txtpak++; // playernum
-							const size_t txtsize = txtpak[0]+1;
+					// copy the textcmds
+					numtxtpak = *txtpak++;
+					for (j = 0; j < numtxtpak; j++)
+					{
+						INT32 k = *txtpak++; // playernum
+						const size_t txtsize = txtpak[0]+1;
 
-							M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize);
-							txtpak += txtsize;
-						}
+						M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize);
+						txtpak += txtsize;
 					}
-
-					neededtic = realend;
 				}
-				else
-					DEBFILE(va("frame not in bound: %u\n", neededtic));
-				break;
-			case PT_RESYNCHING:
-				// Only accept PT_RESYNCHING from the server.
-				if (node != servernode)
-				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHING", node);
 
-					if (server)
-					{
-						XBOXSTATIC char buf[2];
-						buf[0] = (char)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
+				neededtic = realend;
+			}
+			else
+				DEBFILE(va("frame not in bound: %u\n", neededtic));
+			break;
+		case PT_RESYNCHING:
+			// Only accept PT_RESYNCHING from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHING", node);
 
-					break;
+				if (server)
+				{
+					XBOXSTATIC char buf[2];
+					buf[0] = (char)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
 				}
-				resynch_local_inprogress = true;
-				CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
+
 				break;
+			}
+			resynch_local_inprogress = true;
+			CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
+			break;
 #ifdef NEWPING
-			case PT_PING:
-				// Only accept PT_PING from the server.
-				if (node != servernode)
-				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_PING", node);
-
-					if (server)
-					{
-						XBOXSTATIC char buf[2];
-						buf[0] = (char)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
-
-					break;
-				}
+		case PT_PING:
+			// Only accept PT_PING from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_PING", node);
 
-				//Update client ping table from the server.
-				if (!server)
+				if (server)
 				{
-					INT32 i;
-					for (i = 0; i < MAXNETNODES; i++)
-						if (playeringame[i])
-							playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i];
+					XBOXSTATIC char buf[2];
+					buf[0] = (char)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
 				}
 
 				break;
+			}
+
+			//Update client ping table from the server.
+			if (!server)
+			{
+				INT32 i;
+				for (i = 0; i < MAXNETNODES; i++)
+					if (playeringame[i])
+						playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i];
+			}
+
+			break;
 #endif
-			case PT_SERVERCFG:
-				break;
-			case PT_FILEFRAGMENT:
-				if (!server)
-					Got_Filetxpak();
-				break;
-			default:
-				DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
-					netbuffer->packettype, node));
-		} // end switch
-	} // end while
+		case PT_SERVERCFG:
+			break;
+		case PT_FILEFRAGMENT:
+			if (!server)
+				Got_Filetxpak();
+			break;
+		default:
+			DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
+				netbuffer->packettype, node));
+	} // end switch
+}
+
+/**	Handles all received packets, if any
+  *
+  * \todo Add details to this description (lol)
+  *
+  */
+static void GetPackets(void)
+{FILESTAMP
+	XBOXSTATIC SINT8 node; // The packet sender
+FILESTAMP
+
+	player_joining = false;
+
+	while (HGetPacket())
+	{
+		node = (SINT8)doomcom->remotenode;
+
+		if (netbuffer->packettype == PT_CLIENTJOIN && server)
+		{
+			HandleConnect(node);
+			continue;
+		}
+		if (netbuffer->packettype == PT_SERVERSHUTDOWN && node == servernode
+			&& !server && cl_mode != CL_SEARCHING)
+		{
+			HandleShutdown(node);
+			continue;
+		}
+		if (netbuffer->packettype == PT_NODETIMEOUT && node == servernode
+			&& !server && cl_mode != CL_SEARCHING)
+		{
+			HandleTimeout(node);
+			continue;
+		}
+
+#ifndef NONET
+		if (netbuffer->packettype == PT_SERVERINFO)
+		{
+			HandleServerInfo(node);
+			continue;
+		}
+#endif
+
+		if (netbuffer->packettype == PT_PLAYERINFO)
+			continue; // We do nothing with PLAYERINFO, that's for the MS browser.
+
+		// Packet received from someone already playing
+		if (nodeingame[node])
+			HandlePacketFromPlayer(node);
+		// Packet received from someone trying to join
+		else
+			HandlePacketFromAwayNode(node);
+	}
 }
 
 //
@@ -3768,6 +3911,8 @@ static INT16 Consistancy(void)
 {
 	INT32 i;
 	UINT32 ret = 0;
+	thinker_t *th;
+	mobj_t *mo;
 
 	DEBFILE(va("TIC %u ", gametic));
 
@@ -3789,6 +3934,76 @@ static INT16 Consistancy(void)
 	if (!G_PlatformGametype())
 		ret += P_GetRandSeed();
 
+	// !!!
+	/*if (!thinkercap.next)
+		return ret;
+	for (th = thinkercap.next; th != &thinkercap; th = th->next)
+	{
+		if (th->function.acp1 != (actionf_p1)P_MobjThinker)
+			continue;
+
+		mo = (mobj_t *)th;
+
+		if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY))
+		{
+			ret -= mo->type;
+			ret += mo->x;
+			ret -= mo->y;
+			ret += mo->z;
+			ret -= mo->momx;
+			ret += mo->momy;
+			ret -= mo->momz;
+			ret += mo->angle;
+			ret -= mo->flags;
+			ret += mo->flags2;
+			ret -= mo->eflags;
+			if (mo->target)
+			{
+				ret += mo->target->type;
+				ret -= mo->target->x;
+				ret += mo->target->y;
+				ret -= mo->target->z;
+				ret += mo->target->momx;
+				ret -= mo->target->momy;
+				ret += mo->target->momz;
+				ret -= mo->target->angle;
+				ret += mo->target->flags;
+				ret -= mo->target->flags2;
+				ret += mo->target->eflags;
+				ret -= mo->target->state - states;
+				ret += mo->target->tics;
+				ret -= mo->target->sprite;
+				ret += mo->target->frame;
+			}
+			else
+				ret ^= 0x3333;
+			if (mo->tracer && mo->tracer->type != MT_OVERLAY)
+			{
+				ret += mo->tracer->type;
+				ret -= mo->tracer->x;
+				ret += mo->tracer->y;
+				ret -= mo->tracer->z;
+				ret += mo->tracer->momx;
+				ret -= mo->tracer->momy;
+				ret += mo->tracer->momz;
+				ret -= mo->tracer->angle;
+				ret += mo->tracer->flags;
+				ret -= mo->tracer->flags2;
+				ret += mo->tracer->eflags;
+				ret -= mo->tracer->state - states;
+				ret += mo->tracer->tics;
+				ret -= mo->tracer->sprite;
+				ret += mo->tracer->frame;
+			}
+			else
+				ret ^= 0xAAAA;
+			ret -= mo->state - states;
+			ret += mo->tics;
+			ret -= mo->sprite;
+			ret += mo->frame;
+		}
+	}*/
+
 	return (INT16)(ret & 0xFFFF);
 }
 
@@ -3829,7 +4044,7 @@ static void CL_SendClientCmd(void)
 		HSendPacket(servernode, false, 0, packetsize);
 	}
 
-	if (cl_mode == cl_connected || dedicated)
+	if (cl_mode == CL_CONNECTED || dedicated)
 	{
 		// send extra data if needed
 		if (localtextcmd[0])
@@ -4212,12 +4427,12 @@ FILESTAMP
 	// client send the command after a receive of the server
 	// the server send before because in single player is beter
 
-	MasterClient_Ticker(); // acking the master server
+	MasterClient_Ticker(); // Acking the Master Server
 
 	if (!server)
 	{
 		if (!resynch_local_inprogress)
-			CL_SendClientCmd(); // send tic cmd
+			CL_SendClientCmd(); // Send tic cmd
 		hu_resynching = resynch_local_inprogress;
 	}
 	else
@@ -4243,21 +4458,21 @@ FILESTAMP
 					counts = -666;
 				}
 
-			// do not make tics while resynching
+			// Do not make tics while resynching
 			if (counts != -666)
 			{
 				if (maketic + counts >= firstticstosend + BACKUPTICS)
 					counts = firstticstosend+BACKUPTICS-maketic-1;
 
 				for (i = 0; i < counts; i++)
-					SV_Maketic(); // create missed tics and increment maketic
+					SV_Maketic(); // Create missed tics and increment maketic
 
-				for (; tictoclear < firstticstosend; tictoclear++) // clear only when acknoledged
-					D_Clearticcmd(tictoclear);                    // clear the maketic the new tic
+				for (; tictoclear < firstticstosend; tictoclear++) // Clear only when acknowledged
+					D_Clearticcmd(tictoclear);                    // Clear the maketic the new tic
 
 				SV_SendTics();
 
-				neededtic = maketic; // the server is a client too
+				neededtic = maketic; // The server is a client too
 			}
 			else
 				hu_resynching = true;
@@ -4271,7 +4486,7 @@ FILESTAMP
 		M_Ticker();
 		CON_Ticker();
 	}
-	FiletxTicker();
+	SV_FileSendTicker();
 }
 
 /** Returns the number of players playing.
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 14b590926..5b2155552 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -59,7 +59,7 @@ typedef enum
 	// Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility.
 
 	PT_CANFAIL,       // This is kind of a priority. Anything bigger than CANFAIL
-	                  // allows HSendPacket(,true,,) to return false.
+	                  // allows HSendPacket(*, true, *, *) to return false.
 	                  // In addition, this packet can't occupy all the available slots.
 
 	PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file.
@@ -76,11 +76,18 @@ typedef enum
 	NUMPACKETTYPE
 } packettype_t;
 
+#define PACKETDROP
+
+#ifdef PACKETDROP
+void Command_Drop(void);
+void Command_Droprate(void);
+#endif
+
 #if defined(_MSC_VER)
 #pragma pack(1)
 #endif
 
-// client to server packet
+// Client to server packet
 typedef struct
 {
 	UINT8 client_tic;
@@ -89,7 +96,7 @@ typedef struct
 	ticcmd_t cmd;
 } ATTRPACK clientcmd_pak;
 
-// splitscreen packet
+// Splitscreen packet
 // WARNING: must have the same format of clientcmd_pak, for more easy use
 typedef struct
 {
@@ -110,16 +117,16 @@ typedef struct
 	UINT8 starttic;
 	UINT8 numtics;
 	UINT8 numslots; // "Slots filled": Highest player number in use plus one.
-	ticcmd_t cmds[45]; // normally [BACKUPTIC][MAXPLAYERS] but too large
+	ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
 } ATTRPACK servertics_pak;
 
-// sent to client when all consistency data
+// Sent to client when all consistency data
 // for players has been restored
 typedef struct
 {
 	UINT32 randomseed;
 
-	//ctf flag stuff
+	// CTF flag stuff
 	SINT8 flagplayer[2];
 	INT32 flagloose[2];
 	INT32 flagflags[2];
@@ -127,11 +134,11 @@ typedef struct
 	fixed_t flagy[2];
 	fixed_t flagz[2];
 
-	UINT32 ingame;  // spectator bit for each player
-	UINT32 ctfteam; // if not spectator, then which team?
+	UINT32 ingame;  // Spectator bit for each player
+	UINT32 ctfteam; // If not spectator, then which team?
 
 	// Resynch game scores and the like all at once
-	UINT32 score[MAXPLAYERS]; // Everyone's score.
+	UINT32 score[MAXPLAYERS]; // Everyone's score
 	INT16 numboxes[MAXPLAYERS];
 	INT16 totalring[MAXPLAYERS];
 	tic_t realtime[MAXPLAYERS];
@@ -140,14 +147,14 @@ typedef struct
 
 typedef struct
 {
-	//player stuff
+	// Player stuff
 	UINT8 playernum;
 
 	// Do not send anything visual related.
 	// Only send data that we need to know for physics.
-	UINT8 playerstate; //playerstate_t
-	UINT32 pflags; //pflags_t
-	UINT8 panim; //panim_t
+	UINT8 playerstate; // playerstate_t
+	UINT32 pflags; // pflags_t
+	UINT8 panim; // panim_t
 
 	angle_t aiming;
 	INT32 currentweapon;
@@ -174,9 +181,9 @@ typedef struct
 	UINT8 charability;
 	UINT8 charability2;
 	UINT32 charflags;
-	UINT32 thokitem; //mobjtype_t
-	UINT32 spinitem; //mobjtype_t
-	UINT32 revitem; //mobjtype_t
+	UINT32 thokitem; // mobjtype_t
+	UINT32 spinitem; // mobjtype_t
+	UINT32 revitem; // mobjtype_t
 	fixed_t actionspd;
 	fixed_t mindash;
 	fixed_t maxdash;
@@ -230,7 +237,7 @@ typedef struct
 	INT32 onconveyor;
 
 	//player->mo stuff
-	UINT8 hasmo; //boolean
+	UINT8 hasmo; // Boolean
 
 	angle_t angle;
 	fixed_t x;
@@ -257,10 +264,10 @@ typedef struct
 
 typedef struct
 {
-	UINT8 version; // different versions don't work
-	UINT8 subversion; // contains build version
+	UINT8 version; // Different versions don't work
+	UINT8 subversion; // Contains build version
 
-	// server launch stuffs
+	// Server launch stuffs
 	UINT8 serverplayer;
 	UINT8 totalslotnum; // "Slots": highest player number in use plus one.
 
@@ -274,18 +281,18 @@ typedef struct
 
 	UINT8 gametype;
 	UINT8 modifiedgame;
-	SINT8 adminplayer; // needs to be signed
+	SINT8 adminplayer; // Needs to be signed
 
-	char server_context[8]; // unique context id, generated at server startup.
+	char server_context[8]; // Unique context id, generated at server startup.
 
-	UINT8 varlengthinputs[0]; // playernames and netvars
+	UINT8 varlengthinputs[0]; // Playernames and netvars
 } ATTRPACK serverconfig_pak;
 
 typedef struct {
 	UINT8 fileid;
 	UINT32 position;
 	UINT16 size;
-	UINT8 data[0]; // size is variable using hardware_MAXPACKETLENGTH
+	UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH
 } ATTRPACK filetx_pak;
 
 #ifdef _MSC_VER
@@ -294,14 +301,14 @@ typedef struct {
 
 typedef struct
 {
-	UINT8 version; // different versions don't work
-	UINT8 subversion; // contains build version
+	UINT8 version; // Different versions don't work
+	UINT8 subversion; // Contains build version
 	UINT8 localplayers;
 	UINT8 mode;
 } ATTRPACK clientconfig_pak;
 
 #define MAXSERVERNAME 32
-// this packet is too large
+// This packet is too large
 typedef struct
 {
 	UINT8 version;
@@ -367,45 +374,45 @@ typedef struct
 } ATTRPACK plrconfig;
 
 //
-// Network packet data.
+// Network packet data
 //
 typedef struct
 {
 	UINT32 checksum;
-	UINT8 ack; // if not null the node asks for acknowledgement, the receiver must resend the ack
-	UINT8 ackreturn; // the return of the ack number
+	UINT8 ack; // If not zero the node asks for acknowledgement, the receiver must resend the ack
+	UINT8 ackreturn; // The return of the ack number
 
 	UINT8 packettype;
-	UINT8 reserved; // padding
+	UINT8 reserved; // Padding
 	union
 	{
-		clientcmd_pak clientpak;    //      144 bytes
-		client2cmd_pak client2pak;  //      200 bytes
-		servertics_pak serverpak;   //   132495 bytes
-		serverconfig_pak servercfg; //      773 bytes
-		resynchend_pak resynchend;  //
-		resynch_pak resynchpak;     //
-		UINT8 resynchgot;           //
-		UINT8 textcmd[MAXTEXTCMD+1]; //   66049 bytes
-		filetx_pak filetxpak;       //      139 bytes
-		clientconfig_pak clientcfg; //      136 bytes
-		serverinfo_pak serverinfo;  //     1024 bytes
-		serverrefuse_pak serverrefuse; // 65025 bytes
-		askinfo_pak askinfo;        //       61 bytes
-		msaskinfo_pak msaskinfo;    //       22 bytes
-		plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes
-		plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes
+		clientcmd_pak clientpak;            //         144 bytes
+		client2cmd_pak client2pak;          //         200 bytes
+		servertics_pak serverpak;           //      132495 bytes (more around 360, no?)
+		serverconfig_pak servercfg;         //         773 bytes
+		resynchend_pak resynchend;          //
+		resynch_pak resynchpak;             //
+		UINT8 resynchgot;                   //
+		UINT8 textcmd[MAXTEXTCMD+1];        //       66049 bytes (wut??? 64k??? More like 257 bytes...)
+		filetx_pak filetxpak;               //         139 bytes
+		clientconfig_pak clientcfg;         //         136 bytes
+		serverinfo_pak serverinfo;          //        1024 bytes
+		serverrefuse_pak serverrefuse;      //       65025 bytes (somehow I feel like those values are garbage...)
+		askinfo_pak askinfo;                //          61 bytes
+		msaskinfo_pak msaskinfo;            //          22 bytes
+		plrinfo playerinfo[MAXPLAYERS];     //        1152 bytes (I'd say 36~38)
+		plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE)
 #ifdef NEWPING
-		UINT32 pingtable[MAXPLAYERS]; //    128 bytes
+		UINT32 pingtable[MAXPLAYERS];       //         128 bytes
 #endif
-	} u; // this is needed to pack diff packet types data together
+	} u; // This is needed to pack diff packet types data together
 } ATTRPACK doomdata_t;
 
 #if defined(_MSC_VER)
 #pragma pack()
 #endif
 
-#define MAXSERVERLIST 64 // depends only on the display
+#define MAXSERVERLIST 64 // Depends only on the display
 typedef struct
 {
 	SINT8 node;
@@ -416,7 +423,7 @@ extern serverelem_t serverlist[MAXSERVERLIST];
 extern UINT32 serverlistcount;
 extern INT32 mapchangepending;
 
-// points inside doomcom
+// Points inside doomcom
 extern doomdata_t *netbuffer;
 
 extern consvar_t cv_playbackspeed;
@@ -437,7 +444,7 @@ extern consvar_t cv_playbackspeed;
 #define KICK_MSG_CUSTOM_BAN  8
 
 extern boolean server;
-extern boolean dedicated; // for dedicated server
+extern boolean dedicated; // For dedicated server
 extern UINT16 software_MAXPACKETLENGTH;
 extern boolean acceptnewnode;
 extern SINT8 servernode;
@@ -452,11 +459,11 @@ extern UINT32 playerpingtable[MAXPLAYERS];
 
 extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend;
 
-// used in d_net, the only dependence
+// Used in d_net, the only dependence
 tic_t ExpandTics(INT32 low);
 void D_ClientServerInit(void);
 
-// initialise the other field
+// Initialise the other field
 void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum));
 void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam);
 void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player
@@ -474,14 +481,14 @@ void CL_RemoveSplitscreenPlayer(void);
 void CL_Reset(void);
 void CL_ClearPlayer(INT32 playernum);
 void CL_UpdateServerList(boolean internetsearch, INT32 room);
-// is there a game running
+// Is there a game running
 boolean Playing(void);
 
 // Broadcasts special packets to other players
 //  to notify of game exit
 void D_QuitNetGame(void);
 
-//? how many ticks to run?
+//? How many ticks to run?
 void TryRunTics(tic_t realtic);
 
 // extra data for lmps
diff --git a/src/d_net.c b/src/d_net.c
index 03e126b50..52041a8a5 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -31,15 +31,15 @@
 //
 // NETWORKING
 //
-// gametic is the tic about to be (or currently being) run
-// server:
+// gametic is the tic about to (or currently being) run
+// Server:
 //   maketic is the tic that hasn't had control made for it yet
-//   nettics: is the tic for each node
-//   firsttictosend: is the lowest value of nettics
-// client:
-//   neededtic: is the tic needed by the client to run the game
-//   firsttictosend: is used to optimize a condition
-// normally maketic >= gametic > 0
+//   nettics is the tic for each node
+//   firstticstosend is the lowest value of nettics
+// Client:
+//   neededtic is the tic needed by the client to run the game
+//   firstticstosend is used to optimize a condition
+// Normally maketic >= gametic > 0
 
 #define FORCECLOSE 0x8000
 tic_t connectiontimeout = (15*TICRATE);
@@ -129,9 +129,9 @@ boolean Net_GetNetStat(void)
 // -----------------------------------------------------------------
 // Some structs and functions for acknowledgement of packets
 // -----------------------------------------------------------------
-#define MAXACKPACKETS 96 // minimum number of nodes
+#define MAXACKPACKETS 96 // Minimum number of nodes (wat)
 #define MAXACKTOSEND 96
-#define URGENTFREESLOTENUM 10
+#define URGENTFREESLOTNUM 10
 #define ACKTOSENDTIMEOUT (TICRATE/11)
 
 #ifndef NONET
@@ -139,10 +139,10 @@ typedef struct
 {
 	UINT8 acknum;
 	UINT8 nextacknum;
-	UINT8 destinationnode;
-	tic_t senttime;
-	UINT16 length;
-	UINT16 resentnum;
+	UINT8 destinationnode; // The node to send the ack to
+	tic_t senttime; // The time when the ack was sent
+	UINT16 length; // The packet size
+	UINT16 resentnum; // The number of
 	union {
 		SINT8 raw[MAXPACKETLENGTH];
 		doomdata_t data;
@@ -212,11 +212,16 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b)
 	return d;
 }
 
-// return a free acknum and copy netbuffer in the ackpak table
+/** Sets freeack to a free acknum and copies the netbuffer in the ackpak table
+  *
+  * \param freeack  The address to store the free acknum at
+  * \param lowtimer ???
+  * \return True if a free acknum was found
+  */
 static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 {
 	node_t *node = &nodes[doomcom->remotenode];
-	INT32 i, numfreeslote = 0;
+	INT32 i, numfreeslot = 0;
 
 	if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0)
 	{
@@ -227,10 +232,13 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 	for (i = 0; i < MAXACKPACKETS; i++)
 		if (!ackpak[i].acknum)
 		{
-			// for low priority packet, make sure let freeslotes so urgents packets can be sent
-			numfreeslote++;
-			if (netbuffer->packettype >= PT_CANFAIL && numfreeslote < URGENTFREESLOTENUM)
-				continue;
+			// For low priority packets, make sure to let freeslots so urgent packets can be sent
+			if (netbuffer->packettype >= PT_CANFAIL)
+			{
+				numfreeslot++;
+				if (numfreeslot <= URGENTFREESLOTNUM)
+					continue;
+			}
 
 			ackpak[i].acknum = node->nextacknum;
 			ackpak[i].nextacknum = node->nextacknum;
@@ -241,7 +249,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 			ackpak[i].length = doomcom->datalength;
 			if (lowtimer)
 			{
-				// lowtime mean can't be sent now so try it soon as possible
+				// Lowtime means can't be sent now so try it as soon as possible
 				ackpak[i].senttime = 0;
 				ackpak[i].resentnum = 1;
 			}
@@ -254,7 +262,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 
 			*freeack = ackpak[i].acknum;
 
-			sendackpacket++; // for stat
+			sendackpacket++; // For stat
 
 			return true;
 		}
@@ -266,14 +274,14 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 	return false;
 }
 
-// Get a ack to send in the queu of this node
+// Get a ack to send in the queue of this node
 static UINT8 GetAcktosend(INT32 node)
 {
 	nodes[node].lasttimeacktosend_sent = I_GetTime();
 	return nodes[node].firstacktosend;
 }
 
-static void Removeack(INT32 i)
+static void RemoveAck(INT32 i)
 {
 	INT32 node = ackpak[i].destinationnode;
 #ifndef NEWPING
@@ -294,27 +302,27 @@ static void Removeack(INT32 i)
 		Net_CloseConnection(node);
 }
 
-// we have got a packet proceed the ack request and ack return
+// We have got a packet, proceed the ack request and ack return
 static boolean Processackpak(void)
 {
 	INT32 i;
 	boolean goodpacket = true;
 	node_t *node = &nodes[doomcom->remotenode];
 
-	// received an ack return, so remove the ack in the list
+	// Received an ack return, so remove the ack in the list
 	if (netbuffer->ackreturn && cmpack(node->remotefirstack, netbuffer->ackreturn) < 0)
 	{
 		node->remotefirstack = netbuffer->ackreturn;
-		// search the ackbuffer and free it
+		// Search the ackbuffer and free it
 		for (i = 0; i < MAXACKPACKETS; i++)
 			if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes
 				&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
 			{
-				Removeack(i);
+				RemoveAck(i);
 			}
 	}
 
-	// received a packet with ack, queue it to send the ack back
+	// Received a packet with ack, queue it to send the ack back
 	if (netbuffer->ack)
 	{
 		UINT8 ack = netbuffer->ack;
@@ -323,23 +331,23 @@ static boolean Processackpak(void)
 		{
 			DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack));
 			duppacket++;
-			goodpacket = false; // discard packet (duplicate)
+			goodpacket = false; // Discard packet (duplicate)
 		}
 		else
 		{
-			// check if it is not already in the queue
+			// Check if it is not already in the queue
 			for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND)
 				if (node->acktosend[i] == ack)
 				{
 					DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack));
 					duppacket++;
-					goodpacket = false; // discard packet (duplicate)
+					goodpacket = false; // Discard packet (duplicate)
 					break;
 				}
 			if (goodpacket)
 			{
-				// is a good packet so increment the acknowledge number,
-				// then search for a "hole" in the queue
+				// Is a good packet so increment the acknowledge number,
+				// Then search for a "hole" in the queue
 				UINT8 nextfirstack = (UINT8)(node->firstacktosend + 1);
 				if (!nextfirstack)
 					nextfirstack = 1;
@@ -383,10 +391,10 @@ static boolean Processackpak(void)
 						}
 					}
 				}
-				else // out of order packet
+				else // Out of order packet
 				{
-					// don't increment firsacktosend, put it in asktosend queue
-					// will be incremented when the nextfirstack comes (code above)
+					// Don't increment firsacktosend, put it in asktosend queue
+					// Will be incremented when the nextfirstack comes (code above)
 					UINT8 newhead = (UINT8)((node->acktosend_head+1) % MAXACKTOSEND);
 					DEBFILE(va("out of order packet (%d expected)\n", nextfirstack));
 					if (newhead != node->acktosend_tail)
@@ -394,8 +402,8 @@ static boolean Processackpak(void)
 						node->acktosend[node->acktosend_head] = ack;
 						node->acktosend_head = newhead;
 					}
-					else // buffer full discard packet, sender will resend it
-					{ // we can admit the packet but we will not detect the duplication after :(
+					else // Buffer full discard packet, sender will resend it
+					{ // We can admit the packet but we will not detect the duplication after :(
 						DEBFILE("no more freeackret\n");
 						goodpacket = false;
 					}
@@ -430,25 +438,24 @@ static void GotAcks(void)
 				if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode)
 				{
 					if (ackpak[i].acknum == netbuffer->u.textcmd[j])
-						Removeack(i);
-					else
-						// nextacknum is first equal to acknum, then when receiving bigger ack
-						// there is big chance the packet is lost
-						// when resent, nextacknum = nodes[node].nextacknum
-						//    will redo the same but with different value
-					if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0
-						&& ackpak[i].senttime > 0)
-					{
-						ackpak[i].senttime--; // hurry up
-					}
+						RemoveAck(i);
+					// nextacknum is first equal to acknum, then when receiving bigger ack
+					// there is big chance the packet is lost
+					// When resent, nextacknum = nodes[node].nextacknum
+					// will redo the same but with different value
+					else if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0
+							&& ackpak[i].senttime > 0)
+						{
+							ackpak[i].senttime--; // hurry up
+						}
 				}
 }
 #endif
 
 static inline void Net_ConnectionTimeout(INT32 node)
 {
-	// send a very special packet to self (hack the reboundstore queue)
-	// main code will handle it
+	// Send a very special packet to self (hack the reboundstore queue)
+	// Main code will handle it
 	reboundstore[rebound_head].packettype = PT_NODETIMEOUT;
 	reboundstore[rebound_head].ack = 0;
 	reboundstore[rebound_head].ackreturn = 0;
@@ -456,12 +463,12 @@ static inline void Net_ConnectionTimeout(INT32 node)
 	reboundsize[rebound_head] = (INT16)(BASEPACKETSIZE + 1);
 	rebound_head = (rebound_head+1) % MAXREBOUND;
 
-	// do not redo it quickly (if we do not close connection it is
+	// Do not redo it quickly (if we do not close connection it is
 	// for a good reason!)
 	nodes[node].lasttimepacketreceived = I_GetTime();
 }
 
-// resend the data if needed
+// Resend the data if needed
 void Net_AckTicker(void)
 {
 #ifndef NONET
@@ -497,7 +504,7 @@ void Net_AckTicker(void)
 			ackpak[i].senttime = I_GetTime();
 			ackpak[i].resentnum++;
 			ackpak[i].nextacknum = node->nextacknum;
-			retransmit++; // for stat
+			retransmit++; // For stat
 			HSendPacket((INT32)(node - nodes), false, ackpak[i].acknum,
 				(size_t)(ackpak[i].length - BASEPACKETSIZE));
 		}
@@ -505,11 +512,11 @@ void Net_AckTicker(void)
 
 	for (i = 1; i < MAXNETNODES; i++)
 	{
-		// this is something like node open flag
+		// This is something like node open flag
 		if (nodes[i].firstacktosend)
 		{
-			// we haven't sent a packet for a long time
-			// acknowledge packet if needed
+			// We haven't sent a packet for a long time
+			// Acknowledge packet if needed
 			if (nodes[i].lasttimeacktosend_sent + ACKTOSENDTIMEOUT < I_GetTime())
 				Net_SendAcks(i);
 
@@ -523,9 +530,9 @@ void Net_AckTicker(void)
 #endif
 }
 
-// remove last packet received ack before resending the ackret
+// Remove last packet received ack before resending the ackreturn
 // (the higher layer doesn't have room, or something else ....)
-void Net_UnAcknowledgPacket(INT32 node)
+void Net_UnAcknowledgePacket(INT32 node)
 {
 #ifdef NONET
 	(void)node;
@@ -564,7 +571,12 @@ void Net_UnAcknowledgPacket(INT32 node)
 #endif
 }
 
-boolean Net_AllAckReceived(void)
+/** Checks if all acks have been received
+  *
+  * \return True if all acks have been received
+  *
+  */
+static boolean Net_AllAcksReceived(void)
 {
 #ifndef NONET
 	INT32 i;
@@ -577,7 +589,11 @@ boolean Net_AllAckReceived(void)
 	return true;
 }
 
-// wait for all ackreturns with timeout in seconds
+/** Waits for all ackreturns
+  *
+  * \param timeout Timeout in seconds
+  *
+  */
 void Net_WaitAllAckReceived(UINT32 timeout)
 {
 #ifdef NONET
@@ -587,7 +603,7 @@ void Net_WaitAllAckReceived(UINT32 timeout)
 	timeout = tictac + timeout*NEWTICRATE;
 
 	HGetPacket();
-	while (timeout > I_GetTime() && !Net_AllAckReceived())
+	while (timeout > I_GetTime() && !Net_AllAcksReceived())
 	{
 		while (tictac == I_GetTime())
 			I_Sleep();
@@ -598,18 +614,18 @@ void Net_WaitAllAckReceived(UINT32 timeout)
 #endif
 }
 
-static void InitNode(INT32 node)
+static void InitNode(node_t *node)
 {
-	nodes[node].acktosend_head = nodes[node].acktosend_tail = 0;
+	node->acktosend_head = node->acktosend_tail = 0;
 #ifndef NEWPING
-	nodes[node].ping = PINGDEFAULT;
-	nodes[node].varping = VARPINGDEFAULT;
-	nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);
+	node->ping = PINGDEFAULT;
+	node->varping = VARPINGDEFAULT;
+	node->timeout = TIMEOUT(node->ping, node->varping);
 #endif
-	nodes[node].firstacktosend = 0;
-	nodes[node].nextacknum = 1;
-	nodes[node].remotefirstack = 0;
-	nodes[node].flags = 0;
+	node->firstacktosend = 0;
+	node->nextacknum = 1;
+	node->remotefirstack = 0;
+	node->flags = 0;
 }
 
 static void InitAck(void)
@@ -622,9 +638,14 @@ static void InitAck(void)
 #endif
 
 	for (i = 0; i < MAXNETNODES; i++)
-		InitNode(i);
+		InitNode(&nodes[i]);
 }
 
+/** Removes all acks of a given packet type
+  *
+  * \param packettype The packet type to forget
+  *
+  */
 void Net_AbortPacketType(UINT8 packettype)
 {
 #ifdef NONET
@@ -676,8 +697,8 @@ void Net_CloseConnection(INT32 node)
 				ackpak[i].acknum = 0;
 		}
 
-	InitNode(node);
-	AbortSendFiles(node);
+	InitNode(&nodes[node]);
+	SV_AbortSendFiles(node);
 	I_NetFreeNodenum(node);
 #endif
 }
@@ -729,9 +750,15 @@ static void fprintfstring(char *s, size_t len)
 		}
 	if (mode)
 		fprintf(debugfile, "]");
+}
+
+static void fprintfstringnewline(char *s, size_t len)
+{
+	fprintfstring(s, len);
 	fprintf(debugfile, "\n");
 }
 
+/// \warning Keep this up-to-date if you add/remove/rename packet types
 static const char *packettypename[NUMPACKETTYPE] =
 {
 	"NOTHING",
@@ -749,15 +776,22 @@ static const char *packettypename[NUMPACKETTYPE] =
 
 	"ASKINFO",
 	"SERVERINFO",
+	"PLAYERINFO",
 	"REQUESTFILE",
 	"ASKINFOVIAMS",
 
-	"PLAYERCONFIGS",
+	"RESYNCHEND",
+	"RESYNCHGET",
+
 	"FILEFRAGMENT",
 	"TEXTCMD",
 	"TEXTCMD2",
 	"CLIENTJOIN",
 	"NODETIMEOUT",
+	"RESYNCHING",
+#ifdef NEWPING
+	"PING"
+#endif
 };
 
 static void DebugPrintpacket(const char *header)
@@ -770,20 +804,29 @@ static void DebugPrintpacket(const char *header)
 	{
 		case PT_ASKINFO:
 		case PT_ASKINFOVIAMS:
-			fprintf(debugfile, "    time %u\n", (tic_t)LONG(netbuffer->u.askinfo.time)				);
+			fprintf(debugfile, "    time %u\n", (tic_t)LONG(netbuffer->u.askinfo.time));
 			break;
 		case PT_CLIENTJOIN:
 			fprintf(debugfile, "    number %d mode %d\n", netbuffer->u.clientcfg.localplayers,
 				netbuffer->u.clientcfg.mode);
 			break;
 		case PT_SERVERTICS:
+		{
+			servertics_pak *serverpak = &netbuffer->u.serverpak;
+			ticcmd_t *cmd = &serverpak->cmds[serverpak->numslots * serverpak->numtics];
+			size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)cmd;
+
 			fprintf(debugfile, "    firsttic %u ply %d tics %d ntxtcmd %s\n    ",
-				(UINT32)ExpandTics(netbuffer->u.serverpak.starttic), netbuffer->u.serverpak.numslots,
-				netbuffer->u.serverpak.numtics,
-				sizeu1((size_t)(&((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics])));
-			fprintfstring((char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics],(size_t)(
-				&((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics]));
+				(UINT32)ExpandTics(serverpak->starttic), serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd));
+			fprintfstring((char *)cmd, 3);
+			if (ntxtcmd > 4)
+			{
+				fprintf(debugfile, "[%s]", netxcmdnames[*(((UINT8 *)cmd) + 3) - 1]);
+				fprintfstring(((char *)cmd) + 4, ntxtcmd - 4);
+			}
+			fprintf(debugfile, "\n");
 			break;
+		}
 		case PT_CLIENTCMD:
 		case PT_CLIENT2CMD:
 		case PT_CLIENTMIS:
@@ -797,7 +840,8 @@ static void DebugPrintpacket(const char *header)
 		case PT_TEXTCMD:
 		case PT_TEXTCMD2:
 			fprintf(debugfile, "    length %d\n    ", netbuffer->u.textcmd[0]);
-			fprintfstring((char *)netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]);
+			fprintf(debugfile, "[%s]", netxcmdnames[netbuffer->u.textcmd[1] - 1]);
+			fprintfstringnewline((char *)netbuffer->u.textcmd + 2, netbuffer->u.textcmd[0] - 1);
 			break;
 		case PT_SERVERCFG:
 			fprintf(debugfile, "    playerslots %d clientnode %d serverplayer %d "
@@ -813,7 +857,7 @@ static void DebugPrintpacket(const char *header)
 				netbuffer->u.serverinfo.maxplayer, netbuffer->u.serverinfo.mapname,
 				netbuffer->u.serverinfo.fileneedednum,
 				(UINT32)LONG(netbuffer->u.serverinfo.time));
-			fprintfstring((char *)netbuffer->u.serverinfo.fileneeded,
+			fprintfstringnewline((char *)netbuffer->u.serverinfo.fileneeded,
 				(UINT8)((UINT8 *)netbuffer + doomcom->datalength
 				- (UINT8 *)netbuffer->u.serverinfo.fileneeded));
 			break;
@@ -827,20 +871,102 @@ static void DebugPrintpacket(const char *header)
 			break;
 		case PT_REQUESTFILE:
 		default: // write as a raw packet
-			fprintfstring((char *)netbuffer->u.textcmd,
+			fprintfstringnewline((char *)netbuffer->u.textcmd,
 				(UINT8)((UINT8 *)netbuffer + doomcom->datalength - (UINT8 *)netbuffer->u.textcmd));
 			break;
 	}
 }
 #endif
 
+#define PACKETDROP
+
+#ifdef PACKETDROP
+static INT32 packetdropquantity[NUMPACKETTYPE] = {0};
+static INT32 packetdroprate = 0;
+
+void Command_Drop(void)
+{
+	INT32 packetquantity;
+	const char *packetname;
+	size_t i;
+
+	if (COM_Argc() < 2)
+	{
+		CONS_Printf("drop <packettype> [quantity]: drop packets\n"
+					"drop reset: cancel all packet drops");
+		return;
+	}
+
+	if (!(stricmp(COM_Argv(1), "reset") && stricmp(COM_Argv(1), "cancel") && stricmp(COM_Argv(1), "stop")))
+	{
+		memset(packetdropquantity, 0, sizeof(packetdropquantity));
+		return;
+	}
+
+	if (COM_Argc() >= 3)
+	{
+		packetquantity = atoi(COM_Argv(2));
+		if (packetquantity <= 0 && COM_Argv(2)[0] != '0')
+		{
+			CONS_Printf("Invalid quantity\n");
+			return;
+		}
+	}
+	else
+		packetquantity = -1;
+
+	packetname = COM_Argv(1);
+
+	if (!(stricmp(packetname, "all") && stricmp(packetname, "any")))
+		for (i = 0; i < NUMPACKETTYPE; i++)
+			packetdropquantity[i] = packetquantity;
+	else
+	{
+		for (i = 0; i < NUMPACKETTYPE; i++)
+			if (!stricmp(packetname, packettypename[i]))
+			{
+				packetdropquantity[i] = packetquantity;
+				return;
+			}
+
+		CONS_Printf("Unknown packet name\n");
+	}
+}
+
+void Command_Droprate(void)
+{
+	INT32 droprate;
+
+	if (COM_Argc() < 2)
+	{
+		CONS_Printf("Packet drop rate: %d%%\n", packetdroprate);
+		return;
+	}
+
+	droprate = atoi(COM_Argv(1));
+	if ((droprate <= 0 && COM_Argv(1)[0] != '0') || droprate > 100)
+	{
+		CONS_Printf("Packet drop rate must be between 0 and 100!\n");
+		return;
+	}
+
+	packetdroprate = droprate;
+}
+
+static boolean ShouldDropPacket(void)
+{
+	return (packetdropquantity[netbuffer->packettype])
+		|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
+}
+#endif
+
 //
 // HSendPacket
 //
 boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength)
 {
 	doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE);
-	if (node == 0) // packet is to go back to us
+	if (node == 0) // Packet is to go back to us
 	{
 		if ((rebound_head+1) % MAXREBOUND == rebound_tail)
 		{
@@ -871,7 +997,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 	(void)reliable;
 	(void)acknum;
 #else
-	// do this before GetFreeAcknum because this function backup
+	// do this before GetFreeAcknum because this function backups
 	// the current packet
 	doomcom->remotenode = (INT16)node;
 	if (doomcom->datalength <= 0)
@@ -884,7 +1010,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 		return false;
 	}
 
-	if (node < MAXNETNODES) // can be a broadcast
+	if (node < MAXNETNODES) // Can be a broadcast
 		netbuffer->ackreturn = GetAcktosend(node);
 	else
 		netbuffer->ackreturn = 0;
@@ -905,20 +1031,30 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 		netbuffer->ack = acknum;
 
 	netbuffer->checksum = NetbufferChecksum();
-	sendbytes += packetheaderlength + doomcom->datalength; // for stat
+	sendbytes += packetheaderlength + doomcom->datalength; // For stat
 
-	// simulate internet :)
-	if (true || rand()<(INT32)RAND_MAX/5)
+#ifdef PACKETDROP
+	// Simulate internet :)
+	//if (rand() >= (INT32)(RAND_MAX * (PACKETLOSSRATE / 100.f)))
+	if (!ShouldDropPacket())
 	{
+#endif
 #ifdef DEBUGFILE
 		if (debugfile)
-			DebugPrintpacket("SEND");
+			DebugPrintpacket("SENT");
 #endif
 		I_NetSend();
+#ifdef PACKETDROP
 	}
+	else
+	{
+		if (packetdropquantity[netbuffer->packettype] > 0)
+			packetdropquantity[netbuffer->packettype]--;
 #ifdef DEBUGFILE
-	else if (debugfile)
-		DebugPrintpacket("NOTSEND");
+		if (debugfile)
+			DebugPrintpacket("NOT SENT");
+#endif
+	}
 #endif
 
 #endif // ndef NONET
@@ -933,7 +1069,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 //
 boolean HGetPacket(void)
 {
-	// get a packet from self
+	// Get a packet from self
 	if (rebound_tail != rebound_head)
 	{
 		M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]);
@@ -963,11 +1099,11 @@ boolean HGetPacket(void)
 		if (doomcom->remotenode == -1)
 			return false;
 
-		getbytes += packetheaderlength + doomcom->datalength; // for stat
+		getbytes += packetheaderlength + doomcom->datalength; // For stat
 
 		if (doomcom->remotenode >= MAXNETNODES)
 		{
-			DEBFILE(va("receive packet from node %d !\n", doomcom->remotenode));
+			DEBFILE(va("Received packet from node %d!\n", doomcom->remotenode));
 			continue;
 		}
 
diff --git a/src/d_net.h b/src/d_net.h
index 285b44235..190e07a60 100644
--- a/src/d_net.h
+++ b/src/d_net.h
@@ -18,10 +18,10 @@
 #ifndef __D_NET__
 #define __D_NET__
 
-// Max computers in a game.
+// Max computers in a game
 #define MAXNETNODES 32
 #define BROADCASTADDR MAXNETNODES
-#define MAXSPLITSCREENPLAYERS 2 // max number of players on a single computer
+#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer
 
 #define STATLENGTH (TICRATE*2)
 
@@ -32,17 +32,16 @@ extern float lostpercent, duppercent, gamelostpercent;
 extern INT32 packetheaderlength;
 boolean Net_GetNetStat(void);
 extern INT32 getbytes;
-extern INT64 sendbytes; // realtime updated
+extern INT64 sendbytes; // Realtime updated
 
 extern SINT8 nodetoplayer[MAXNETNODES];
-extern SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
-extern UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen
-extern boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
+extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen)
+extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
+extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
 
 void Net_AckTicker(void);
-boolean Net_AllAckReceived(void);
 
-// if reliable return true if packet sent, 0 else
+// If reliable return true if packet sent, 0 else
 boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum,
 	size_t packetlength);
 boolean HGetPacket(void);
@@ -52,9 +51,10 @@ void D_SaveBan(void);
 #endif
 boolean D_CheckNetGame(void);
 void D_CloseConnection(void);
-void Net_UnAcknowledgPacket(INT32 node);
+void Net_UnAcknowledgePacket(INT32 node);
 void Net_CloseConnection(INT32 node);
 void Net_AbortPacketType(UINT8 packettype);
 void Net_SendAcks(INT32 node);
 void Net_WaitAllAckReceived(UINT32 timeout);
+
 #endif
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 4f73a2564..d70805e1c 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -365,6 +365,35 @@ boolean splitscreen = false;
 boolean circuitmap = false;
 INT32 adminplayer = -1;
 
+/// \warning Keep this up-to-date if you add/remove/rename net text commands
+const char *netxcmdnames[MAXNETXCMD - 1] =
+{
+	"NAMEANDCOLOR",
+	"WEAPONPREF",
+	"KICK",
+	"NETVAR",
+	"SAY",
+	"MAP",
+	"EXITLEVEL",
+	"ADDFILE",
+	"PAUSE",
+	"ADDPLAYER",
+	"TEAMCHANGE",
+	"CLEARSCORES",
+	"LOGIN",
+	"VERIFIED",
+	"RANDOMSEED",
+	"RUNSOC",
+	"REQADDFILE",
+	"DELFILE",
+	"SETMOTD",
+	"SUICIDE",
+#ifdef HAVE_BLUA
+	"LUACMD",
+	"LUAVAR"
+#endif
+};
+
 // =========================================================================
 //                           SERVER STARTUP
 // =========================================================================
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index c090699f1..d8fae72f7 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -162,6 +162,8 @@ typedef enum
 	MAXNETXCMD
 } netxcmd_t;
 
+extern const char *netxcmdnames[MAXNETXCMD - 1];
+
 #if defined(_MSC_VER)
 #pragma pack(1)
 #endif
diff --git a/src/d_netfil.c b/src/d_netfil.c
index 85196217f..0601f1dfe 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -62,34 +62,37 @@
 
 #include <errno.h>
 
-static void SendFile(INT32 node, const char *filename, UINT8 fileid);
+static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid);
 
-// sender structure
+// Sender structure
 typedef struct filetx_s
 {
 	INT32 ram;
-	char *filename; // name of the file or ptr of the data in ram
-	UINT32 size;
+	union {
+		char *filename; // Name of the file
+		char *ram; // Pointer to the data in RAM
+	} id;
+	UINT32 size; // Size of the file
 	UINT8 fileid;
-	INT32 node; // destination
-	struct filetx_s *next; // a queue
+	INT32 node; // Destination
+	struct filetx_s *next; // Next file in the list
 } filetx_t;
 
-// current transfers (one for each node)
+// Current transfers (one for each node)
 typedef struct filetran_s
 {
-	filetx_t *txlist;
-	UINT32 position;
-	FILE *currentfile;
+	filetx_t *txlist; // Linked list of all files for the node
+	UINT32 position; // The current position in the file
+	FILE *currentfile; // The file currently being sent/received
 } filetran_t;
 static filetran_t transfer[MAXNETNODES];
 
-// read time of file: stat _stmtime
-// write time of file: utime
+// Read time of file: stat _stmtime
+// Write time of file: utime
 
-// receiver structure
-INT32 fileneedednum;
-fileneeded_t fileneeded[MAX_WADFILES];
+// Receiver structure
+INT32 fileneedednum; // Number of files needed to join the server
+fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
 char downloaddir[256] = "DOWNLOAD";
 
 #ifdef CLIENT_LOADINGSCREEN
@@ -100,6 +103,7 @@ INT32 lastfilenum = 0;
 /** Fills a serverinfo packet with information about wad files loaded.
   *
   * \todo Give this function a better name since it is in global scope.
+  *
   */
 UINT8 *PutFileNeeded(void)
 {
@@ -111,19 +115,19 @@ UINT8 *PutFileNeeded(void)
 
 	for (i = 0; i < numwadfiles; i++)
 	{
-		// if it has only music/sound lumps, mark it as unimportant
+		// If it has only music/sound lumps, mark it as unimportant
 		if (W_VerifyNMUSlumps(wadfiles[i]->filename))
 			filestatus = 0;
 		else
-			filestatus = 1; // important
+			filestatus = 1; // Important
 
 		// Store in the upper four bits
 		if (!cv_downloading.value)
-			filestatus += (2 << 4); // won't send
+			filestatus += (2 << 4); // Won't send
 		else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024))
-			filestatus += (0 << 4); // won't send
+			filestatus += (0 << 4); // Won't send
 		else
-			filestatus += (1 << 4); // will send if requested
+			filestatus += (1 << 4); // Will send if requested
 
 		bytesused += (nameonlylength(wadfilename) + 22);
 
@@ -144,7 +148,12 @@ UINT8 *PutFileNeeded(void)
 	return p;
 }
 
-// parse the serverinfo packet and fill fileneeded table on client
+/** Parses the serverinfo packet and fills the fileneeded table on client
+  *
+  * \param fileneedednum_parm The number of files needed to join the server
+  * \param fileneededstr The memory block containing the list of needed files
+  *
+  */
 void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
 {
 	INT32 i;
@@ -155,14 +164,14 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
 	p = (UINT8 *)fileneededstr;
 	for (i = 0; i < fileneedednum; i++)
 	{
-		fileneeded[i].status = FS_NOTFOUND;
-		filestatus = READUINT8(p);
+		fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
+		filestatus = READUINT8(p); // The first byte is the file status
 		fileneeded[i].important = (UINT8)(filestatus & 3);
 		fileneeded[i].willsend = (UINT8)(filestatus >> 4);
-		fileneeded[i].totalsize = READUINT32(p);
-		fileneeded[i].phandle = NULL;
-		READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH);
-		READMEM(p, fileneeded[i].md5sum, 16);
+		fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
+		fileneeded[i].file = NULL; // The file isn't open yet
+		READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
+		READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum
 	}
 }
 
@@ -171,13 +180,16 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
 	fileneedednum = 1;
 	fileneeded[0].status = FS_REQUESTED;
 	fileneeded[0].totalsize = UINT32_MAX;
-	fileneeded[0].phandle = NULL;
+	fileneeded[0].file = NULL;
 	memset(fileneeded[0].md5sum, 0, 16);
 	strcpy(fileneeded[0].filename, tmpsave);
 }
 
 /** Checks the server to see if we CAN download all the files,
   * before starting to create them and requesting.
+  *
+  * \return True if we can download all the files
+  *
   */
 boolean CL_CheckDownloadable(void)
 {
@@ -239,8 +251,12 @@ boolean CL_CheckDownloadable(void)
 	return false;
 }
 
-/** Send requests for files in the ::fileneeded table with a status of
+/** Sends requests for files in the ::fileneeded table with a status of
   * ::FS_NOTFOUND.
+  *
+  * \return True if the packet was successfully sent
+  * \note Sends a PT_REQUESTFILE packet
+  *
   */
 boolean CL_SendRequestFile(void)
 {
@@ -298,11 +314,17 @@ void Got_RequestFilePak(INT32 node)
 		if (id == 0xFF)
 			break;
 		READSTRINGN(p, wad, MAX_WADPATH);
-		SendFile(node, wad, id);
+		SV_SendFile(node, wad, id);
 	}
 }
 
-// client check if the fileneeded aren't already loaded or on the disk
+/** Checks if the files needed aren't already loaded or on the disk
+  *
+  * \return 0 if some files are missing
+  *         1 if all files exist
+  *         2 if some already loaded files are not requested or are in a different order
+  *
+  */
 INT32 CL_CheckFiles(void)
 {
 	INT32 i, j;
@@ -333,7 +355,7 @@ INT32 CL_CheckFiles(void)
 			}
 			if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename))
 			{
-				// unimportant on our side. still don't care.
+				// Unimportant on our side. still don't care.
 				++j;
 				continue;
 			}
@@ -343,11 +365,11 @@ INT32 CL_CheckFiles(void)
 			if (i >= fileneedednum || j >= numwadfiles)
 				return 2;
 
-			// for the sake of speed, only bother with a md5 check
+			// For the sake of speed, only bother with a md5 check
 			if (memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16))
 				return 2;
 
-			// it's accounted for! let's keep going.
+			// It's accounted for! let's keep going.
 			CONS_Debug(DBG_NETPLAY, "'%s' accounted for\n", fileneeded[i].filename);
 			fileneeded[i].status = FS_OPEN;
 			++i;
@@ -360,7 +382,7 @@ INT32 CL_CheckFiles(void)
 	{
 		CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
 
-		// check in allready loaded files
+		// Check in already loaded files
 		for (j = 1; wadfiles[j]; j++)
 		{
 			nameonly(strcpy(wadfilename, wadfiles[j]->filename));
@@ -383,7 +405,7 @@ INT32 CL_CheckFiles(void)
 	return ret;
 }
 
-// load it now
+// Load it now
 void CL_LoadServerFiles(void)
 {
 	INT32 i;
@@ -394,7 +416,7 @@ void CL_LoadServerFiles(void)
 	for (i = 1; i < fileneedednum; i++)
 	{
 		if (fileneeded[i].status == FS_OPEN)
-			continue; // already loaded
+			continue; // Already loaded
 		else if (fileneeded[i].status == FS_FOUND)
 		{
 			P_AddWadFile(fileneeded[i].filename, NULL);
@@ -423,133 +445,200 @@ void CL_LoadServerFiles(void)
 			DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename));
 		}
 		else if (fileneeded[i].important)
-			I_Error("Try to load file %s with status of %d\n", fileneeded[i].filename,
-				fileneeded[i].status);
+		{
+			char *s;
+			switch(fileneeded[i].status)
+			{
+			case FS_NOTFOUND:
+				s = "FS_NOTFOUND";
+				break;
+			case FS_REQUESTED:
+				s = "FS_REQUESTED";
+				break;
+			case FS_DOWNLOADING:
+				s = "FS_DOWNLOADING";
+				break;
+			default:
+				s = "unknown";
+				break;
+			}
+			I_Error("Try to load file \"%s\" with status of %d (%s)\n", fileneeded[i].filename,
+				fileneeded[i].status, s);
+		}
 	}
 }
 
-// little optimization to test if there is a file in the queue
-static INT32 filetosend = 0;
+// Number of files to send
+// Little optimization to quickly test if there is a file in the queue
+static INT32 filestosend = 0;
 
-static void SendFile(INT32 node, const char *filename, UINT8 fileid)
+/** Adds a file to the file list for a node
+  *
+  * \param node The node to send the file to
+  * \param filename The file to send
+  * \param fileid ???
+  * \sa SV_SendRam
+  *
+  */
+static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
 {
-	filetx_t **q;
-	filetx_t *p;
+	filetx_t **q; // A pointer to the "next" field of the last file in the list
+	filetx_t *p; // The new file request
 	INT32 i;
 	char wadfilename[MAX_WADPATH];
 
+	// Find the last file in the list and set a pointer to its "next" field
 	q = &transfer[node].txlist;
 	while (*q)
 		q = &((*q)->next);
+
+	// Allocate a file request and append it to the file list
 	p = *q = (filetx_t *)malloc(sizeof (filetx_t));
-	if (p)
-		memset(p, 0, sizeof (filetx_t));
-	else
-		I_Error("SendFile: No more ram\n");
-	p->filename = (char *)malloc(MAX_WADPATH);
-	if (!p->filename)
-		I_Error("SendFile: No more ram\n");
+	if (!p)
+		I_Error("SV_SendFile: No more memory\n");
+
+	// Initialise with zeros
+	memset(p, 0, sizeof (filetx_t));
+
+	// Allocate the file name
+	p->id.filename = (char *)malloc(MAX_WADPATH);
+	if (!p->id.filename)
+		I_Error("SV_SendFile: No more memory\n");
 
-	// a minimum of security, can get only file in srb2 direcory
-	strlcpy(p->filename, filename, MAX_WADPATH);
-	nameonly(p->filename);
+	// Set the file name and get rid of the path
+	strlcpy(p->id.filename, filename, MAX_WADPATH);
+	nameonly(p->id.filename);
 
-	// check first in wads loaded the majority of case
+	// Look for the requested file through all loaded files
 	for (i = 0; wadfiles[i]; i++)
 	{
 		strlcpy(wadfilename, wadfiles[i]->filename, MAX_WADPATH);
 		nameonly(wadfilename);
-		if (!stricmp(wadfilename, p->filename))
+		if (!stricmp(wadfilename, p->id.filename))
 		{
-			// copy filename with full path
-			strlcpy(p->filename, wadfiles[i]->filename, MAX_WADPATH);
+			// Copy file name with full path
+			strlcpy(p->id.filename, wadfiles[i]->filename, MAX_WADPATH);
 			break;
 		}
 	}
 
+	// Handle non-loaded file requests
 	if (!wadfiles[i])
 	{
 		DEBFILE(va("%s not found in wadfiles\n", filename));
-		// this formerly checked if (!findfile(p->filename, NULL, true))
+		// This formerly checked if (!findfile(p->id.filename, NULL, true))
 
-		// not found
-		// don't inform client (probably hacker)
+		// Not found
+		// Don't inform client (probably someone who thought they could leak 2.2 ACZ)
 		DEBFILE(va("Client %d request %s: not found\n", node, filename));
-		free(p->filename);
+		free(p->id.filename);
 		free(p);
 		*q = NULL;
 		return;
 	}
 
+	// Handle huge file requests (i.e. bigger than cv_maxsend.value KB)
 	if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)
 	{
-		// too big
-		// don't inform client (client sucks, man)
+		// Too big
+		// Don't inform client (client sucks, man)
 		DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename));
-		free(p->filename);
+		free(p->id.filename);
 		free(p);
 		*q = NULL;
 		return;
 	}
 
 	DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node));
-	p->ram = SF_FILE;
+	p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
 	p->fileid = fileid;
-	p->next = NULL; // end of list
-	filetosend++;
+	p->next = NULL; // End of list
+	filestosend++;
 }
 
-void SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid)
+/** Adds a memory block to the file list for a node
+  *
+  * \param node The node to send the memory block to
+  * \param data The memory block to send
+  * \param size The size of the block in bytes
+  * \param freemethod How to free the block after it has been sent
+  * \param fileid ???
+  * \sa SV_SendFile
+  *
+  */
+void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid)
 {
-	filetx_t **q;
-	filetx_t *p;
+	filetx_t **q; // A pointer to the "next" field of the last file in the list
+	filetx_t *p; // The new file request
 
+	// Find the last file in the list and set a pointer to its "next" field
 	q = &transfer[node].txlist;
 	while (*q)
 		q = &((*q)->next);
+
+	// Allocate a file request and append it to the file list
 	p = *q = (filetx_t *)malloc(sizeof (filetx_t));
-	if (p)
-		memset(p, 0, sizeof (filetx_t));
-	else
-		I_Error("SendRam: No more ram\n");
-	p->ram = freemethod;
-	p->filename = data;
+	if (!p)
+		I_Error("SV_SendRam: No more memory\n");
+
+	// Initialise with zeros
+	memset(p, 0, sizeof (filetx_t));
+
+	p->ram = freemethod; // Remember how to free the memory block for when we're done sending it
+	p->id.ram = data;
 	p->size = (UINT32)size;
 	p->fileid = fileid;
-	p->next = NULL; // end of list
+	p->next = NULL; // End of list
 
-	DEBFILE(va("Sending ram %p(size:%u) to %d (id=%u)\n",p->filename,p->size,node,fileid));
+	DEBFILE(va("Sending ram %p(size:%u) to %d (id=%u)\n",p->id.ram,p->size,node,fileid));
 
-	filetosend++;
+	filestosend++;
 }
 
-static void EndSend(INT32 node)
+/** Stops sending a file for a node, and removes the file request from the list,
+  * either because the file has been fully sent or because the node was disconnected
+  *
+  * \param node The destination
+  *
+  */
+static void SV_EndFileSend(INT32 node)
 {
 	filetx_t *p = transfer[node].txlist;
+
+	// Free the file request according to the freemethod parameter used with SV_SendFile/Ram
 	switch (p->ram)
 	{
-		case SF_FILE:
+		case SF_FILE: // It's a file, close it and free its filename
 			if (transfer[node].currentfile)
 				fclose(transfer[node].currentfile);
-			free(p->filename);
+			free(p->id.filename);
 			break;
-		case SF_Z_RAM:
-			Z_Free(p->filename);
+		case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free
+			Z_Free(p->id.ram);
 			break;
-		case SF_RAM:
-			free(p->filename);
-		case SF_NOFREERAM:
+		case SF_RAM: // It's a memory block allocated with malloc, use free
+			free(p->id.ram);
+		case SF_NOFREERAM: // Nothing to free
 			break;
 	}
+
+	// Remove the file request from the list
 	transfer[node].txlist = p->next;
-	transfer[node].currentfile = NULL;
 	free(p);
-	filetosend--;
+
+	// Indicate that the transmission is over
+	transfer[node].currentfile = NULL;
+
+	filestosend--;
 }
 
 #define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH)
 
-void FiletxTicker(void)
+/** Handles file transmission
+  *
+  *
+  */
+void SV_FileSendTicker(void)
 {
 	static INT32 currentnode = 0;
 	filetx_pak *p;
@@ -557,12 +646,12 @@ void FiletxTicker(void)
 	filetx_t *f;
 	INT32 packetsent = PACKETPERTIC, ram, i;
 
-	if (!filetosend)
+	if (!filestosend)
 		return;
 	if (!packetsent)
 		packetsent++;
 	// (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth)
-	while (packetsent-- && filetosend != 0)
+	while (packetsent-- && filestosend != 0)
 	{
 		for (i = currentnode, ram = 0; ram < MAXNETNODES;
 			i = (i+1) % MAXNETNODES, ram++)
@@ -571,24 +660,25 @@ void FiletxTicker(void)
 				goto found;
 		}
 		// no transfer to do
-		I_Error("filetosend=%d but no filetosend found\n", filetosend);
+		I_Error("filestosend=%d but no file to send found\n", filestosend);
 	found:
 		currentnode = (i+1) % MAXNETNODES;
 		f = transfer[i].txlist;
 		ram = f->ram;
 
-		if (!transfer[i].currentfile) // file not already open
+		// Open the file if it isn't open yet, or
+		if (!transfer[i].currentfile)
 		{
-			if (!ram)
+			if (!ram) // Sending a file
 			{
 				long filesize;
 
 				transfer[i].currentfile =
-					fopen(f->filename, "rb");
+					fopen(f->id.filename, "rb");
 
 				if (!transfer[i].currentfile)
 					I_Error("File %s does not exist",
-						f->filename);
+						f->id.filename);
 
 				fseek(transfer[i].currentfile, 0, SEEK_END);
 				filesize = ftell(transfer[i].currentfile);
@@ -596,46 +686,49 @@ void FiletxTicker(void)
 				// Nobody wants to transfer a file bigger
 				// than 4GB!
 				if (filesize >= LONG_MAX)
-					I_Error("filesize of %s is too large", f->filename);
-				if (-1 == filesize)
-					I_Error("Error getting filesize of %s", f->filename);
+					I_Error("filesize of %s is too large", f->id.filename);
+				if (filesize == -1)
+					I_Error("Error getting filesize of %s", f->id.filename);
 
 				f->size = (UINT32)filesize;
 				fseek(transfer[i].currentfile, 0, SEEK_SET);
 			}
-			else
-				transfer[i].currentfile = (FILE *)1;
+			else // Sending RAM
+				transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open
 			transfer[i].position = 0;
 		}
 
+		// Build a packet containing a file fragment
 		p = &netbuffer->u.filetxpak;
 		size = software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE);
 		if (f->size-transfer[i].position < size)
 			size = f->size-transfer[i].position;
 		if (ram)
-			M_Memcpy(p->data, &f->filename[transfer[i].position], size);
+			M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
 		else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
-			I_Error("FiletxTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->filename, transfer[i].position, strerror(ferror(transfer[i].currentfile)));
+			I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, strerror(ferror(transfer[i].currentfile)));
 		p->position = LONG(transfer[i].position);
-		// put flag so receiver know the totalsize
+		// Put flag so receiver knows the total size
 		if (transfer[i].position + size == f->size)
 			p->position |= LONG(0x80000000);
 		p->fileid = f->fileid;
 		p->size = SHORT((UINT16)size);
 		netbuffer->packettype = PT_FILEFRAGMENT;
-		if (!HSendPacket(i, true, 0, FILETXHEADER + size)) // reliable SEND
-		{ // not sent for some odd reason, retry at next call
+
+		// Send the packet
+		if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND
+		{ // Success
+			transfer[i].position = (UINT32)(transfer[i].position + size);
+			if (transfer[i].position == f->size) // Finish?
+				SV_EndFileSend(i);
+		}
+		else
+		{ // Not sent for some odd reason, retry at next call
 			if (!ram)
-				fseek(transfer[i].currentfile,transfer[i].position,SEEK_SET);
-			// exit the while (can't send this one so why should i send the next?)
+				fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET);
+			// Exit the while (can't send this one so why should i send the next?)
 			break;
 		}
-		else // success
-		{
-			transfer[i].position = (UINT32)(size+transfer[i].position);
-			if (transfer[i].position == f->size) //  finish ?
-				EndSend(i);
-		}
 	}
 }
 
@@ -646,16 +739,18 @@ void Got_Filetxpak(void)
 
 	if (filenum >= fileneedednum)
 	{
-		DEBFILE(va("fileframent not needed %d>%d\n",filenum, fileneedednum));
+		DEBFILE(va("fileframent not needed %d>%d\n", filenum, fileneedednum));
 		return;
 	}
 
 	if (fileneeded[filenum].status == FS_REQUESTED)
 	{
-		if (fileneeded[filenum].phandle) I_Error("Got_Filetxpak: allready open file\n");
-			fileneeded[filenum].phandle = fopen(fileneeded[filenum].filename, "wb");
-		if (!fileneeded[filenum].phandle) I_Error("Can't create file %s: %s",fileneeded[filenum].filename, strerror(errno));
-			CONS_Printf("\r%s...\n",fileneeded[filenum].filename);
+		if (fileneeded[filenum].file)
+			I_Error("Got_Filetxpak: already open file\n");
+		fileneeded[filenum].file = fopen(fileneeded[filenum].filename, "wb");
+		if (!fileneeded[filenum].file)
+			I_Error("Can't create file %s: %s", fileneeded[filenum].filename, strerror(errno));
+		CONS_Printf("\r%s...\n",fileneeded[filenum].filename);
 		fileneeded[filenum].currentsize = 0;
 		fileneeded[filenum].status = FS_DOWNLOADING;
 	}
@@ -664,24 +759,24 @@ void Got_Filetxpak(void)
 	{
 		UINT32 pos = LONG(netbuffer->u.filetxpak.position);
 		UINT16 size = SHORT(netbuffer->u.filetxpak.size);
-		// use a special tric to know when file is finished (not allways used)
-		// WARNING: filepak can arrive out of order so don't stop now !
+		// Use a special trick to know when the file is complete (not always used)
+		// WARNING: file fragments can arrive out of order so don't stop yet!
 		if (pos & 0x80000000)
 		{
 			pos &= ~0x80000000;
 			fileneeded[filenum].totalsize = pos + size;
 		}
-		// we can receive packet in the wrong order, anyway all os support gaped file
-		fseek(fileneeded[filenum].phandle,pos,SEEK_SET);
-		if (fwrite(netbuffer->u.filetxpak.data,size,1,fileneeded[filenum].phandle)!=1)
-			I_Error("Can't write to %s: %s\n",fileneeded[filenum].filename, strerror(ferror(fileneeded[filenum].phandle)));
+		// We can receive packet in the wrong order, anyway all os support gaped file
+		fseek(fileneeded[filenum].file, pos, SEEK_SET);
+		if (fwrite(netbuffer->u.filetxpak.data,size,1,fileneeded[filenum].file) != 1)
+			I_Error("Can't write to %s: %s\n",fileneeded[filenum].filename, strerror(ferror(fileneeded[filenum].file)));
 		fileneeded[filenum].currentsize += size;
 
-		// finished?
+		// Finished?
 		if (fileneeded[filenum].currentsize == fileneeded[filenum].totalsize)
 		{
-			fclose(fileneeded[filenum].phandle);
-			fileneeded[filenum].phandle = NULL;
+			fclose(fileneeded[filenum].file);
+			fileneeded[filenum].file = NULL;
 			fileneeded[filenum].status = FS_FOUND;
 			CONS_Printf(M_GetText("Downloading %s...(done)\n"),
 				fileneeded[filenum].filename);
@@ -689,8 +784,8 @@ void Got_Filetxpak(void)
 	}
 	else
 		I_Error("Received a file not requested\n");
-	// send ack back quickly
 
+	// Send ack back quickly
 	if (++filetime == 3)
 	{
 		Net_SendAcks(servernode);
@@ -702,33 +797,39 @@ void Got_Filetxpak(void)
 #endif
 }
 
-void AbortSendFiles(INT32 node)
+/** Cancels all file requests for a node
+ *
+ * \param node The destination
+ * \sa SV_EndFileSend
+ *
+ */
+void SV_AbortSendFiles(INT32 node)
 {
 	while (transfer[node].txlist)
-		EndSend(node);
+		SV_EndFileSend(node);
 }
 
 void CloseNetFile(void)
 {
 	INT32 i;
-	// is sending?
+	// Is sending?
 	for (i = 0; i < MAXNETNODES; i++)
-		AbortSendFiles(i);
+		SV_AbortSendFiles(i);
 
-	// receiving a file?
+	// Receiving a file?
 	for (i = 0; i < MAX_WADFILES; i++)
-		if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].phandle)
+		if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
 		{
-			fclose(fileneeded[i].phandle);
-			// file is not complete delete it
+			fclose(fileneeded[i].file);
+			// File is not complete delete it
 			remove(fileneeded[i].filename);
 		}
 
-	// remove FILEFRAGMENT from acknledge list
+	// Remove PT_FILEFRAGMENT from acknowledge list
 	Net_AbortPacketType(PT_FILEFRAGMENT);
 }
 
-// functions cut and pasted from doomatic :)
+// Functions cut and pasted from Doomatic :)
 
 void nameonly(char *s)
 {
diff --git a/src/d_netfil.h b/src/d_netfil.h
index a68119f10..e82b57d67 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -29,21 +29,21 @@ typedef enum
 	FS_FOUND,
 	FS_REQUESTED,
 	FS_DOWNLOADING,
-	FS_OPEN, // is opened and used in w_wad
+	FS_OPEN, // Is opened and used in w_wad
 	FS_MD5SUMBAD
 } filestatus_t;
 
 typedef struct
 {
 	UINT8 important;
-	UINT8 willsend; // is the server willing to send it?
+	UINT8 willsend; // Is the server willing to send it?
 	char filename[MAX_WADPATH];
 	UINT8 md5sum[16];
-	// used only for download
-	FILE *phandle;
+	// Used only for download
+	FILE *file;
 	UINT32 currentsize;
 	UINT32 totalsize;
-	filestatus_t status; // the value returned by recsearch
+	filestatus_t status; // The value returned by recsearch
 } fileneeded_t;
 
 extern INT32 fileneedednum;
@@ -58,28 +58,24 @@ UINT8 *PutFileNeeded(void);
 void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr);
 void CL_PrepareDownloadSaveGame(const char *tmpsave);
 
-// check file list in wadfiles return 0 when a file is not found
-//                                    1 if all file are found
-//                                    2 if you cannot connect (different wad version or
-//                                                   no enought space to download files)
 INT32 CL_CheckFiles(void);
 void CL_LoadServerFiles(void);
-void SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod,
+void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod,
 	UINT8 fileid);
 
-void FiletxTicker(void);
+void SV_FileSendTicker(void);
 void Got_Filetxpak(void);
 
 boolean CL_CheckDownloadable(void);
 boolean CL_SendRequestFile(void);
 void Got_RequestFilePak(INT32 node);
 
-void AbortSendFiles(INT32 node);
+void SV_AbortSendFiles(INT32 node);
 void CloseNetFile(void);
 
 boolean fileexist(char *filename, time_t ptime);
 
-// search a file in the wadpath, return FS_FOUND when found
+// Search a file in the wadpath, return FS_FOUND when found
 filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum,
 	boolean completepath);
 filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);
-- 
GitLab