diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 4448aaae042732fb6a52cf99236486b2e5656019..af2be129f09106fa05d12fa8a0f548a0c7181b1a 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -1265,8 +1265,12 @@ static boolean CL_SendJoin(void)
 	if (splitscreen || botingame)
 		localplayers++;
 	netbuffer->u.clientcfg.localplayers = localplayers;
+	netbuffer->u.clientcfg._255 = 255;
+	netbuffer->u.clientcfg.packetversion = PACKETVERSION;
 	netbuffer->u.clientcfg.version = VERSION;
 	netbuffer->u.clientcfg.subversion = SUBVERSION;
+	strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION,
+			sizeof netbuffer->u.clientcfg.application);
 	strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME);
 	strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME);
 	return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
@@ -1277,8 +1281,12 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
 	UINT8 *p;
 
 	netbuffer->packettype = PT_SERVERINFO;
+	netbuffer->u.serverinfo._255 = 255;
+	netbuffer->u.serverinfo.packetversion = PACKETVERSION;
 	netbuffer->u.serverinfo.version = VERSION;
 	netbuffer->u.serverinfo.subversion = SUBVERSION;
+	strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION,
+			sizeof netbuffer->u.serverinfo.application);
 	// return back the time value so client can compute their ping
 	netbuffer->u.serverinfo.time = (tic_t)LONG(servertime);
 	netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime);
@@ -1712,12 +1720,21 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
 		if (serverlistcount >= MAXSERVERLIST)
 			return; // list full
 
+		if (info->_255 != 255)
+			return;/* old packet format */
+
+		if (info->packetversion != PACKETVERSION)
+			return;/* old new packet format */
+
 		if (info->version != VERSION)
 			return; // Not same version.
 
 		if (info->subversion != SUBVERSION)
 			return; // Close, but no cigar.
 
+		if (strcmp(info->application, SRB2APPLICATION))
+			return;/* that's a different mod */
+
 		i = serverlistcount++;
 	}
 
@@ -3509,6 +3526,12 @@ static void HandleConnect(SINT8 node)
 
 	if (bannednode && bannednode[node])
 		SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
+	else if (netbuffer->u.clientcfg._255 != 255 ||
+			netbuffer->u.clientcfg.packetversion != PACKETVERSION)
+		SV_SendRefuse(node, "Incompatible packet formats.");
+	else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION,
+				sizeof netbuffer->u.clientcfg.application))
+		SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible.");
 	else if (netbuffer->u.clientcfg.version != VERSION
 		|| netbuffer->u.clientcfg.subversion != SUBVERSION)
 		SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
@@ -3631,6 +3654,8 @@ static void HandleServerInfo(SINT8 node)
 	const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE;
 	netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff);
 	netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0;
+	netbuffer->u.serverinfo.application
+		[sizeof netbuffer->u.serverinfo.application - 1] = '\0';
 
 	SL_InsertServer(&netbuffer->u.serverinfo, node);
 }
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 4ba4ee0eb7a1a08ad5639191cf18a4a96bf2a520..49f8afc7630c6123a705f2ed2e66d3d150cab07b 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -19,6 +19,16 @@
 #include "tables.h"
 #include "d_player.h"
 
+/*
+The 'packet version' may be used with packets whose
+format is expected to change between versions.
+
+This version is independent of the mod name, and standard
+version and subversion. It should only account for the
+basic fields of the packet, and change infrequently.
+*/
+#define PACKETVERSION 0
+
 // Network play related stuff.
 // There is a data struct that stores network
 //  communication related stuff, and another
@@ -320,8 +330,13 @@ typedef struct {
 #pragma warning(default : 4200)
 #endif
 
+#define MAXAPPLICATION 16
+
 typedef struct
 {
+	UINT8 _255;/* see serverinfo_pak */
+	UINT8 packetversion;
+	char application[MAXAPPLICATION];
 	UINT8 version; // Different versions don't work
 	UINT8 subversion; // Contains build version
 	UINT8 localplayers;
@@ -334,6 +349,14 @@ typedef struct
 // This packet is too large
 typedef struct
 {
+	/*
+	In the old packet, 'version' is the first field. Now that field is set
+	to 255 always, so older versions won't be confused with the new
+	versions or vice-versa.
+	*/
+	UINT8 _255;
+	UINT8 packetversion;
+	char  application[MAXAPPLICATION];
 	UINT8 version;
 	UINT8 subversion;
 	UINT8 numberofplayer;
diff --git a/src/doomdef.h b/src/doomdef.h
index 51a15bd64d3e023271308ea41475d4bf6566cbed..5f7ec8577a31c611c3feade186c10d39b1ae4ce8 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -130,6 +130,9 @@ extern FILE *logstream;
 extern char logfilename[1024];
 #endif
 
+/* A mod name to further distinguish versions. */
+#define SRB2APPLICATION "SRB2"
+
 //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
 #ifdef DEVELOP
 #define VERSION    0 // Game version