From 096921cbbf112de9d5416e6421b225b8274b3f7d Mon Sep 17 00:00:00 2001
From: toasterbabe <rollerorbital@gmail.com>
Date: Sat, 18 Mar 2017 13:03:29 +0000
Subject: [PATCH] Added a bit of a fun limitation.

* Made it so (player->availabilities & 1 << skinnum) is only true if skins[skinnum] DOES have an availability method, and always false otherwise.
* This means that setting your availabilities to INT32_MAX is no longer the equivalent of having gotten all skins.
* This means we can detect and kick cheat engine script kiddies who try to fool the server that they can use everything.
* This means availabilities of 0x00 is now valid, so make it all F's for an invalid not-in-game.
---
 src/d_clisrv.c |  5 ++---
 src/d_netcmd.c | 11 +++++++++++
 src/r_things.c |  2 +-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 492a8a6458..847c22169d 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -1366,8 +1366,7 @@ static boolean SV_SendServerConfig(INT32 node)
 	// which is nice and easy for us to detect
 	memset(netbuffer->u.servercfg.playerskins, 0xFF, sizeof(netbuffer->u.servercfg.playerskins));
 	memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor));
-	// ...except for availabilities, where 00 is nonexistent
-	memset(netbuffer->u.servercfg.playeravailabilities, 0x00, sizeof(netbuffer->u.servercfg.playeravailabilities));
+	memset(netbuffer->u.servercfg.playeravailabilities, 0xFF, sizeof(netbuffer->u.servercfg.playeravailabilities));
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
@@ -3498,7 +3497,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
 			{
 				if (netbuffer->u.servercfg.playerskins[j] == 0xFF
 				 && netbuffer->u.servercfg.playercolor[j] == 0xFF
-				 && netbuffer->u.servercfg.playeravailabilities[j] == 0x00)
+				 && netbuffer->u.servercfg.playeravailabilities[j] == 0xFFFFFFFF)
 					continue; // not in game
 
 				playeringame[j] = true;
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 51b9e28ca6..ce1a631b6d 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1329,6 +1329,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
 	if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer]))
 	{
 		boolean kick = false;
+		INT32 s;
 
 		// team colors
 		if (G_GametypeHasTeams())
@@ -1343,6 +1344,16 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
 		if (!p->skincolor)
 			kick = true;
 
+		// availabilities
+		for (s = 0; s < MAXSKINS; s++)
+		{
+			if (!skins[s].availability && (p->availabilities & (1 << s)))
+			{
+				kick = true;
+				break;
+			}
+		}
+
 		if (kick)
 		{
 			XBOXSTATIC UINT8 buf[2];
diff --git a/src/r_things.c b/src/r_things.c
index 5280db73a5..0a6230c8f4 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -2561,7 +2561,7 @@ UINT32 R_GetSkinAvailabilities(void)
 
 	for (s = 0; s < MAXSKINS; s++)
 	{
-		if (!skins[s].availability || unlockables[skins[s].availability - 1].unlocked)
+		if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked)
 			response |= (1 << s);
 	}
 	return response;
-- 
GitLab