diff -r 043adb17ae25 src/c_cmds.cpp
--- a/src/c_cmds.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/c_cmds.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -80,6 +80,7 @@
 #include "cl_commands.h"
 #include "cooperative.h"
 #include "survival.h"
+#include "m_cheat.h"
 
 extern FILE *Logfile;
 extern bool insave;
@@ -299,7 +300,22 @@
 		return;
 
 	if ( NETWORK_GetState( ) == NETSTATE_CLIENT )
+	{
+		// [Dusk] Don't bother sending a request to the server when we're spectating.
+		// Spectator movement is entirely client-side and thus we can noclip on our own.
+		if ( players[consoleplayer].bSpectating )
+		{
+			cht_DoCheat( &players[consoleplayer], CHT_NOCLIP );
+
+			// [Dusk] If we are recording a demo, we need to write this noclip use down
+			// so that it can be re-enacted correctly
+			if ( CLIENTDEMO_IsRecording( ))
+				CLIENTDEMO_WriteLocalCommand( CLD_LCMD_NOCLIP, NULL );
+			return;
+		}
+
 		CLIENTCOMMANDS_GenericCheat( CHT_NOCLIP );
+	}
 	else
 	{
 		Net_WriteByte (DEM_GENERICCHEAT);
diff -r 043adb17ae25 src/c_dispatch.cpp
--- a/src/c_dispatch.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/c_dispatch.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -598,7 +598,7 @@
 
 						// [BB] We need to record this for the demo.
 						if ( CLIENTDEMO_IsRecording( ))
-							CLIENTDEMO_WriteLocalCommand( CLD_CENTERVIEW, NULL );
+							CLIENTDEMO_WriteLocalCommand( CLD_LCMD_CENTERVIEW, NULL );
 					}
 				}
 			}
diff -r 043adb17ae25 src/cl_demo.cpp
--- a/src/cl_demo.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/cl_demo.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -71,6 +71,7 @@
 #include "version.h"
 #include "templates.h"
 #include "r_translate.h"
+#include "m_cheat.h"
 
 //*****************************************************************************
 //	PROTOTYPES
@@ -494,34 +495,44 @@
 				}
 			}
 			break;
-		case CLD_INVUSE:
+		case CLD_LOCALCOMMAND:
 
+			switch( static_cast<ClientDemoLocalCommand>( NETWORK_ReadByte( &g_ByteStream )))
 			{
-				AInventory	*pInventory;
+			case CLD_LCMD_INVUSE:
 
-				pszString = NETWORK_ReadString( &g_ByteStream );
+				{
+					AInventory	*pInventory;
+
+					pszString = NETWORK_ReadString( &g_ByteStream );
+
+					if ( players[consoleplayer].mo )
+					{
+						pInventory = players[consoleplayer].mo->FindInventory( pszString );
+						if ( pInventory )
+							players[consoleplayer].mo->UseInventory( pInventory );
+					}
+				}
+				break;
+			case CLD_LCMD_CENTERVIEW:
 
 				if ( players[consoleplayer].mo )
-				{
-					pInventory = players[consoleplayer].mo->FindInventory( pszString );
-					if ( pInventory )
-						players[consoleplayer].mo->UseInventory( pInventory );
-				}
+					players[consoleplayer].mo->pitch = 0;
+				break;
+			case CLD_LCMD_TAUNT:
+
+				PLAYER_Taunt( &players[consoleplayer] );
+				break;
+			case CLD_LCMD_NOCLIP:
+
+				cht_DoCheat( &players[consoleplayer], CHT_NOCLIP );
+				break;
 			}
 			break;
-		case CLD_CENTERVIEW:
-
-			if ( players[consoleplayer].mo )
-				players[consoleplayer].mo->pitch = 0;
-			break;
-		case CLD_TAUNT:
-
-			PLAYER_Taunt( &players[consoleplayer] );
-			break;
 		case CLD_DEMOEND:
 
 			CLIENTDEMO_FinishPlaying( );
-			return;
+			break;
 		default:
 
 #ifdef _DEBUG
@@ -663,29 +674,18 @@
 
 //*****************************************************************************
 //
-void CLIENTDEMO_WriteLocalCommand( LONG lCommand, const char *pszArg )
+void CLIENTDEMO_WriteLocalCommand( ClientDemoLocalCommand command, const char* pszArg )
 {
-	if ( pszArg )
-		clientdemo_CheckDemoBuffer( (ULONG)strlen( pszArg ) + 1 );
+	if ( pszArg != NULL )
+		clientdemo_CheckDemoBuffer( (ULONG)strlen( pszArg ) + 2 );
 	else
-		clientdemo_CheckDemoBuffer( 1 );
+		clientdemo_CheckDemoBuffer( 2 );
 
-	switch ( lCommand )
-	{
-	case CLD_INVUSE:
+	NETWORK_WriteByte( &g_ByteStream, CLD_LOCALCOMMAND );
+	NETWORK_WriteByte( &g_ByteStream, command );
 
-		NETWORK_WriteByte( &g_ByteStream, CLD_INVUSE );
+	if ( pszArg != NULL )
 		NETWORK_WriteString( &g_ByteStream, pszArg );
-		break;
-	case CLD_CENTERVIEW:
-
-		NETWORK_WriteByte( &g_ByteStream, CLD_CENTERVIEW );
-		break;
-	case CLD_TAUNT:
-
-		NETWORK_WriteByte( &g_ByteStream, CLD_TAUNT );
-		break;
-	}
 }
 
 //*****************************************************************************
diff -r 043adb17ae25 src/cl_demo.h
--- a/src/cl_demo.h	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/cl_demo.h	Sat Apr 05 02:25:17 2014 +0300
@@ -70,15 +70,21 @@
 	CLD_USERINFO,
 	CLD_BODYSTART,
 	CLD_TICCMD,
-	CLD_INVUSE,
-	CLD_CENTERVIEW,
-	CLD_TAUNT,
+	CLD_LOCALCOMMAND, // [Dusk]
 	CLD_DEMOEND,
 	CLD_DEMOWADS, // [Dusk]
 
 	NUM_DEMO_COMMANDS
 };
 
+enum ClientDemoLocalCommand
+{
+	CLD_LCMD_INVUSE,
+	CLD_LCMD_CENTERVIEW,
+	CLD_LCMD_TAUNT,
+	CLD_LCMD_NOCLIP,
+};
+
 //*****************************************************************************
 //	PROTOTYPES
 
@@ -96,7 +102,7 @@
 void		CLIENTDEMO_DoPlayDemo( const char *pszDemoName );
 void		CLIENTDEMO_FinishPlaying( void );
 LONG		CLIENTDEMO_GetGameticOffset( void );
-void		CLIENTDEMO_WriteLocalCommand( LONG lCommand, const char *pszArg );
+void		CLIENTDEMO_WriteLocalCommand( ClientDemoLocalCommand command, const char *pszArg );
 void		CLIENTDEMO_ReadDemoWads( void );
 BYTESTREAM_s *CLIENTDEMO_GetDemoStream( void );
 
diff -r 043adb17ae25 src/cl_main.cpp
--- a/src/cl_main.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/cl_main.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -3588,7 +3588,7 @@
 		CLIENTCOMMANDS_WeaponSelect( pPlayer->PendingWeapon->GetClass( ));
 
 		if ( CLIENTDEMO_IsRecording( ))
-			CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, pPlayer->PendingWeapon->GetClass( )->TypeName.GetChars( ) );
+			CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, pPlayer->PendingWeapon->GetClass( )->TypeName.GetChars( ) );
 	}
 }
 
@@ -4127,8 +4127,8 @@
 			CLIENTCOMMANDS_WeaponSelect( pPlayer->ReadyWeapon->GetClass( ));
 
 			if ( CLIENTDEMO_IsRecording( ))
-				CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, pPlayer->ReadyWeapon->GetClass( )->TypeName.GetChars( ) );
-			// [BB] When playing a demo, we will bring up what we recorded with CLD_INVUSE.
+				CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, pPlayer->ReadyWeapon->GetClass( )->TypeName.GetChars( ) );
+			// [BB] When playing a demo, we will bring up what we recorded with CLD_LCMD_INVUSE.
 			else if ( CLIENTDEMO_IsPlaying() )
 				PLAYER_ClearWeapon ( pPlayer );
 		}
diff -r 043adb17ae25 src/g_game.cpp
--- a/src/g_game.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/g_game.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -345,7 +345,7 @@
 			players[consoleplayer].mo->pitch = 0;
 
 		if ( CLIENTDEMO_IsRecording( ))
-			CLIENTDEMO_WriteLocalCommand( CLD_CENTERVIEW, NULL );
+			CLIENTDEMO_WriteLocalCommand( CLD_LCMD_CENTERVIEW, NULL );
 	}
 }
 
diff -r 043adb17ae25 src/g_shared/a_weapons.cpp
--- a/src/g_shared/a_weapons.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/g_shared/a_weapons.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -129,7 +129,7 @@
 			CLIENTCOMMANDS_WeaponSelect( useweap->GetClass( ));
 
 			if ( CLIENTDEMO_IsRecording( ))
-				CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, useweap->GetClass( )->TypeName.GetChars( ) );
+				CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, useweap->GetClass( )->TypeName.GetChars( ) );
 		}
 		else if ( ( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( Owner->player->bIsBot == true ) )
 			SERVERCOMMANDS_SetPlayerPendingWeapon( static_cast<ULONG> ( Owner->player - players ) );
@@ -364,7 +364,7 @@
 					CLIENTCOMMANDS_WeaponSelect( this->GetClass( ));
 
 					if ( CLIENTDEMO_IsRecording( ))
-						CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, this->GetClass( )->TypeName.GetChars( ) );
+						CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, this->GetClass( )->TypeName.GetChars( ) );
 				}
 				else if ( ( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( Owner->player->bIsBot == true ) )
 					SERVERCOMMANDS_SetPlayerPendingWeapon( static_cast<ULONG> ( Owner->player - players ) );
@@ -390,7 +390,7 @@
 						CLIENTCOMMANDS_WeaponSelect( this->GetClass( ));
 
 						if ( CLIENTDEMO_IsRecording( ))
-							CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, this->GetClass( )->TypeName.GetChars( ) );
+							CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, this->GetClass( )->TypeName.GetChars( ) );
 					}
 					else if ( ( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( Owner->player->bIsBot == true ) )
 						SERVERCOMMANDS_SetPlayerPendingWeapon( static_cast<ULONG> ( Owner->player - players ) );
@@ -717,7 +717,7 @@
 					CLIENTCOMMANDS_WeaponSelect( SisterWeapon->GetClass( ));
 
 					if ( CLIENTDEMO_IsRecording( ))
-						CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, SisterWeapon->GetClass( )->TypeName.GetChars( ) );
+						CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, SisterWeapon->GetClass( )->TypeName.GetChars( ) );
 				}
 			}
 		}
@@ -731,7 +731,7 @@
 				CLIENTCOMMANDS_WeaponSelect( SisterWeapon->GetClass( ));
 
 				if ( CLIENTDEMO_IsRecording( ))
-					CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, SisterWeapon->GetClass( )->TypeName.GetChars( ) );
+					CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, SisterWeapon->GetClass( )->TypeName.GetChars( ) );
 			}
 		}
 	}
diff -r 043adb17ae25 src/m_cheat.cpp
--- a/src/m_cheat.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/m_cheat.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -517,10 +517,6 @@
 	if (!*msg)              // [SO] Don't print blank lines!
 		return;
 
-	// [BB] Spectators may use noclip, so the server shouldn't print the "cheater" message.
-	if ( ( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( cheat == CHT_NOCLIP ) && player->bSpectating )
-		return;
-
 	if( ( cheat != CHT_CHASECAM )
 		|| ( !( GAMEMODE_GetFlags( GAMEMODE_GetCurrentMode( )) & GMF_COOPERATIVE )
 			&& ( player->bSpectating == false ) && !(dmflags2 & DF2_CHASECAM))){
diff -r 043adb17ae25 src/p_interaction.cpp
--- a/src/p_interaction.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/p_interaction.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -2881,7 +2881,7 @@
 
 	// Set the ready and pending weapon.
 	// [BB] When playing a client side demo, the weapon for the consoleplayer will
-	// be selected by a recorded CLD_INVUSE command.
+	// be selected by a recorded CLD_LCMD_INVUSE command.
 	if ( ( CLIENTDEMO_IsPlaying() == false ) || ( pPlayer - players ) != consoleplayer )
 		pPlayer->ReadyWeapon = pPlayer->PendingWeapon = pWeapon;
 
@@ -2893,7 +2893,7 @@
 		CLIENTCOMMANDS_WeaponSelect( pWeapon->GetClass( ));
 
 		if ( CLIENTDEMO_IsRecording( ))
-			CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, pWeapon->GetClass( )->TypeName.GetChars( ) );
+			CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, pWeapon->GetClass( )->TypeName.GetChars( ) );
 	}
 	// [BB] Make sure to inform clients of bot weapon changes.
 	else if ( ( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( pPlayer->bIsBot == true ) )
@@ -3078,6 +3078,6 @@
 			CLIENTCOMMANDS_Taunt( );
 
 		if ( CLIENTDEMO_IsRecording( ))
-			CLIENTDEMO_WriteLocalCommand( CLD_TAUNT, NULL );
+			CLIENTDEMO_WriteLocalCommand( CLD_LCMD_TAUNT, NULL );
 	}
 }
diff -r 043adb17ae25 src/p_user.cpp
--- a/src/p_user.cpp	Sun Mar 30 23:25:35 2014 +0300
+++ b/src/p_user.cpp	Sat Apr 05 02:25:17 2014 +0300
@@ -820,7 +820,7 @@
 			if (( CLIENTDEMO_IsRecording( )) &&
 				( CLIENT_IsParsingPacket( ) == false ))
 			{
-				CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, best->GetClass( )->TypeName.GetChars( ) );
+				CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, best->GetClass( )->TypeName.GetChars( ) );
 			}
 		}
 		// [BB] The server needs to tell the clients about bot weapon changes.
@@ -859,7 +859,7 @@
 				CLIENTCOMMANDS_WeaponSelect( best->GetClass( ));
 
 				if ( CLIENTDEMO_IsRecording( ))
-					CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, best->GetClass( )->TypeName.GetChars( ) );
+					CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, best->GetClass( )->TypeName.GetChars( ) );
 			}
 		}
 	}
@@ -1336,7 +1336,7 @@
 					player->StartingWeaponName = item ? item->GetClass()->TypeName : NAME_None;
 				}
 				// [BB] When playing a client side demo, the default weapon for the consoleplayer
-				// will be selected by a recorded CLD_INVUSE command.
+				// will be selected by a recorded CLD_LCMD_INVUSE command.
 				else if ( ( CLIENTDEMO_IsPlaying() == false ) || ( player - players ) != consoleplayer )
 					player->ReadyWeapon = player->PendingWeapon = static_cast<AWeapon *> (item);
 			}
@@ -1350,7 +1350,7 @@
 		CLIENTCOMMANDS_WeaponSelect( player->PendingWeapon->GetClass( ));
 
 		if ( CLIENTDEMO_IsRecording( ))
-			CLIENTDEMO_WriteLocalCommand( CLD_INVUSE, player->PendingWeapon->GetClass( )->TypeName.GetChars( ) );
+			CLIENTDEMO_WriteLocalCommand( CLD_LCMD_INVUSE, player->PendingWeapon->GetClass( )->TypeName.GetChars( ) );
 	}
 
 	// [BB] Ugly hack: Stuff for the Doom player. Moved here since the Doom player
