Index: src/console_cmds.cpp =================================================================== --- src/console_cmds.cpp (revision 11336) +++ src/console_cmds.cpp (working copy) @@ -668,6 +668,51 @@ return true; } +DEF_CONSOLE_CMD(ConMoveClient) +{ + NetworkClientInfo *ci; + uint16 client_index; + PlayerID player_index; + + if (argc == 0) { + IConsoleHelp("Move a player to another company. Usage: move []"); + IConsoleHelp("For client-id see 'clients', company-id must be between 1 and 8, ommit if moving to spectators"); + return true; + } + + client_index = (uint16)atoi(argv[1]); + player_index = (argc == 3) ? (PlayerID)(atoi(argv[2]) - 1) : PLAYER_SPECTATOR; + + if (client_index == NETWORK_SERVER_INDEX) { + IConsoleError("Silly boy, you can not move the server!"); + return true; + } + + if (client_index == 0) { + IConsoleError("Invalid client"); + return true; + } + + ci = NetworkFindClientInfoFromIndex(client_index); + + if ((!IsValidPlayer(player_index) || player_index > ActivePlayerCount()) && player_index != PLAYER_SPECTATOR) { + IConsolePrintF(_icolour_err, "Company does not exist. Company-id must be between 1 and %d.", MAX_PLAYERS); + return true; + } + + IConsolePrintF(_icolour_err, "[move] client %d to company %d.", client_index, player_index+1); + + if (ci != NULL) { + ci->client_playas = player_index; + NetworkUpdateClientInfo(client_index); + SEND_COMMAND(PACKET_CLIENT_MOVE)(NetworkFindClientStateFromIndex(client_index), client_index, player_index); + } else { + IConsoleError("Client not found"); + } + + return true; +} + DEF_CONSOLE_CMD(ConResetCompany) { const Player *p; @@ -1565,6 +1610,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 11336) +++ src/network/core/tcp.h (working copy) @@ -54,6 +54,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_server.cpp =================================================================== --- src/network/network_server.cpp (revision 11336) +++ src/network/network_server.cpp (working copy) @@ -590,6 +590,17 @@ cs->Send_Packet(p); } +DEF_SERVER_SEND_COMMAND_PARAM(PACKET_CLIENT_MOVE)(NetworkTCPSocketHandler *cs, uint16 client_index, uint8 player_index) +{ + Packet *p = NetworkSend_Init(PACKET_CLIENT_MOVE); + + DEBUG(net, 0, "[move] making client %d player %d", client_index, player_index); + + p->Send_uint16(client_index); + p->Send_uint8(player_index); + cs->Send_Packet(p); +} + // ********** // Receiving functions // DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkTCPSocketHandler *cs, Packet *p @@ -1239,6 +1250,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 Index: src/network/network_server.h =================================================================== --- src/network/network_server.h (revision 11336) +++ src/network/network_server.h (working copy) @@ -11,6 +11,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 NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]); void NetworkServer_HandleChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index); Index: src/network/network_client.cpp =================================================================== --- src/network/network_client.cpp (revision 11336) +++ src/network/network_client.cpp (working copy) @@ -789,6 +789,28 @@ return NETWORK_RECV_STATUS_OKAY; } +DEF_CLIENT_RECEIVE_COMMAND(PACKET_CLIENT_MOVE) +{ + uint16 client_index; + PlayerID player_index; + + client_index = p->Recv_uint16(); + player_index = (Owner)p->Recv_uint8(); + + DEBUG(net, 0, "[move] %d becoming player %d", client_index, player_index); + + if (client_index == _network_own_client_index) { + + if (!IsValidPlayer(player_index) || player_index > ActivePlayerCount()) { + player_index = PLAYER_SPECTATOR; + } + + _network_playas = player_index; + SetLocalPlayer(player_index); + } + + return NETWORK_RECV_STATUS_OKAY; +} // The layout for the receive-functions by the client @@ -833,6 +855,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