Index: src/console_cmds.cpp
===================================================================
--- src/console_cmds.cpp	(revision 13397)
+++ src/console_cmds.cpp	(working copy)
@@ -592,6 +592,46 @@
 	return true;
 }
 
+DEF_CONSOLE_CMD(ConMoveClient)
+{
+	NetworkClientInfo *ci;
+	uint16 index;
+	PlayerID new_player;
+
+	if (argc < 2) {
+		IConsoleHelp("Move a player to another company. Usage: move <client-id> [<company-id>]");
+		IConsoleHelp("For client-id see 'clients', company-id must be between 1 and 8, ommit if moving to spectators");
+		return true;
+	}
+
+	index = atoi(argv[1]);
+	new_player = (argc == 3) ? (PlayerID)(atoi(argv[2])-1) : PLAYER_SPECTATOR; 
+	
+	if (index == NETWORK_SERVER_INDEX) {
+		IConsoleError("Silly boy, you can not move the server!");
+		return true;
+	}
+
+	ci = NetworkFindClientInfoFromIndex(index);
+	if (ci == NULL) {
+		IConsoleError("Invalid client");
+		return true;
+	}
+
+	if (!IsValidPlayer(new_player) && new_player != PLAYER_SPECTATOR) {
+		IConsoleError("Company does not exist, see command 'players'.");
+		return true;
+	}
+
+	/* safe to update, update first the actual client, then all clients */
+	ci->client_playas = new_player;
+	NetworkServerSendMove(index, new_player);
+	NetworkUpdateClientInfo(index);
+
+	IConsolePrintF(CC_DEFAULT, "[move] client %d to company %d.", index, min(new_player+1, PLAYER_SPECTATOR));
+	return true;
+}
+
 DEF_CONSOLE_CMD(ConResetCompany)
 {
 	const Player *p;
@@ -1411,6 +1451,8 @@
 	IConsoleCmdRegister("rcon",            ConRcon);
 	IConsoleCmdHookAdd("rcon",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
+	IConsoleCmdRegister("move",            ConMoveClient);
+	IConsoleCmdHookAdd("move",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 	IConsoleCmdRegister("reset_company",   ConResetCompany);
 	IConsoleCmdHookAdd("reset_company",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 	IConsoleAliasRegister("clean_company", "reset_company %A");
Index: src/network/core/tcp.h
===================================================================
--- src/network/core/tcp.h	(revision 13397)
+++ src/network/core/tcp.h	(working copy)
@@ -55,6 +55,7 @@
 	PACKET_CLIENT_RCON,
 	PACKET_SERVER_CHECK_NEWGRFS,
 	PACKET_CLIENT_NEWGRFS_CHECKED,
+	PACKET_CLIENT_MOVE,
 	PACKET_END                   ///< Must ALWAYS be on the end of this list!! (period)
 };
 
Index: src/network/network_func.h
===================================================================
--- src/network/network_func.h	(revision 13397)
+++ src/network/network_func.h	(working copy)
@@ -53,6 +53,7 @@
 NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
 const char* GetPlayerIP(const NetworkClientInfo *ci);
 
+void NetworkServerSendMove(uint16 client_index, PlayerID new_player);
 void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string);
 void NetworkServerSendError(uint16 client_index, NetworkErrorCode error);
 void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
Index: src/network/network_server.cpp
===================================================================
--- src/network/network_server.cpp	(revision 13397)
+++ src/network/network_server.cpp	(working copy)
@@ -599,6 +599,17 @@
 	cs->Send_Packet(p);
 }
 
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_CLIENT_MOVE)(NetworkTCPSocketHandler *cs, uint16 client_index, PlayerID new_player)
+{
+	Packet *p = NetworkSend_Init(PACKET_CLIENT_MOVE);
+
+	DEBUG(net, 0, "[move] client %d to player %d", client_index, min(new_player+1, PLAYER_SPECTATOR));
+
+	p->Send_uint16(client_index);
+	p->Send_uint8(new_player);
+	cs->Send_Packet(p);
+}
+
 // **********
 // Receiving functions
 //   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkTCPSocketHandler *cs, Packet *p
@@ -1248,6 +1259,7 @@
 	RECEIVE_COMMAND(PACKET_CLIENT_RCON),
 	NULL, /*PACKET_CLIENT_CHECK_NEWGRFS,*/
 	RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED),
+	NULL /*PACKET_CLIENT_MOVE,*/
 };
 
 // If this fails, check the array above with network_data.h
@@ -1640,6 +1652,11 @@
 	}
 }
 
+void NetworkServerSendMove(uint16 client_index, PlayerID new_player)
+{
+	SEND_COMMAND(PACKET_CLIENT_MOVE)(NetworkFindClientStateFromIndex(client_index), client_index, new_player);
+}
+
 void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string)
 {
 	SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(client_index), colour_code, string);
Index: src/network/network_server.h
===================================================================
--- src/network/network_server.h	(revision 13397)
+++ src/network/network_server.h	(working copy)
@@ -13,6 +13,7 @@
 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN);
 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkTCPSocketHandler *cs, uint16 color, const char *command);
+DEF_SERVER_SEND_COMMAND_PARAM(PACKET_CLIENT_MOVE)(NetworkTCPSocketHandler *cs, uint16 client_index, uint8 player_index);
 
 bool NetworkServer_ReadPackets(NetworkTCPSocketHandler *cs);
 void NetworkServer_Tick(bool send_frame);
Index: src/network/network_client.cpp
===================================================================
--- src/network/network_client.cpp	(revision 13397)
+++ src/network/network_client.cpp	(working copy)
@@ -7,6 +7,7 @@
 #include "../stdafx.h"
 #include "../debug.h"
 #include "../openttd.h"
+#include "../gfx_func.h"
 #include "network_internal.h"
 #include "core/tcp.h"
 #include "network_client.h"
@@ -396,6 +397,7 @@
 //  which is always an unique number on a server.
 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
 {
+	const Player *player;
 	NetworkClientInfo *ci;
 	uint16 index = p->Recv_uint16();
 	PlayerID playas = (Owner)p->Recv_uint8();
@@ -416,8 +418,25 @@
 			// Client name changed, display the change
 			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", name);
 		} else if (playas != ci->client_playas) {
-			// The player changed from client-player..
-			// Do not display that for now
+			/* Client has been moved to another company or to spectator, show a message. */
+			if (ci->client_playas != PLAYER_NEW_COMPANY && ci->client_playas != PLAYER_INACTIVE_CLIENT) {
+				/* if not valid player, force spectator, else check player exists */
+				if (!IsValidPlayer(playas)) {
+					playas = PLAYER_SPECTATOR;
+				} else {
+					/* only if it's a valid player, actually get the player and check it */
+					player = GetPlayer(playas);
+					if (!player->is_active) {
+						playas = PLAYER_SPECTATOR;
+					}
+				}
+				
+				if (playas == PLAYER_SPECTATOR || playas > MAX_PLAYERS) {
+					NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, ci->client_name, "'%s' Moved To Spectators", ci->client_name);
+				} else {
+					NetworkTextMessage(NETWORK_ACTION_SERVER_MESSAGE, CC_DEFAULT, false, ci->client_name, "'%s' Moved To Company #%d", ci->client_name, playas+1);
+				}
+			}
 		}
 
 		ci->client_playas = playas;
@@ -857,6 +876,51 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
+DEF_CLIENT_RECEIVE_COMMAND(PACKET_CLIENT_MOVE)
+{
+	const Player *player;
+	uint16 client_index;
+	PlayerID player_index;
+	
+	/* Nothing more in this packet... */
+	client_index = p->Recv_uint16();
+	player_index = (Owner)p->Recv_uint8();
+	
+	if (client_index == 0) {
+		/* deffinately an invalide client id, debug message and do nothing. */
+		DEBUG(net, 0, "[move] received client index = 0");
+		return NETWORK_RECV_STATUS_OKAY;
+	}
+	
+	const NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
+	/* Just make sure we do not try to use a client_index that does not exist */
+	if (ci != NULL) {
+		/* if not valid player, force spectator, else check player exists */
+		if (!IsValidPlayer(player_index)) {
+			player_index = PLAYER_SPECTATOR;
+		} else {
+			/* only if it's a valid player, actually get the player and check it */
+			player = GetPlayer(player_index);
+			if (!player->is_active) {
+				player_index = PLAYER_SPECTATOR;
+			}
+		}
+		
+		if (client_index == _network_own_client_index) {
+			/* this packet is actually for this client... apply the new player_index */
+			DEBUG(net, 0, "[move] client %d to player %d", client_index, min(player_index+1, PLAYER_SPECTATOR));
+			
+			_network_playas = player_index;
+			SetLocalPlayer(player_index);
+			
+			/* Disable any buttons in any windows the client is now not supposed to get to, and do it fast. */
+			/* If this is not done fast enough, it can cause the client to be kicked or have an assert! */
+			MarkWholeScreenDirty();
+		}
+	}
+	
+	return NETWORK_RECV_STATUS_OKAY;
+}
 
 
 // The layout for the receive-functions by the client
@@ -901,6 +965,7 @@
 	NULL, /*PACKET_CLIENT_RCON,*/
 	RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS),
 	NULL, /*PACKET_CLIENT_NEWGRFS_CHECKED,*/
+	RECEIVE_COMMAND(PACKET_CLIENT_MOVE),
 };
 
 // If this fails, check the array above with network_data.h
