diff --git a/console_cmds.c b/console_cmds.c index 1da493a22b..d426b99d7c 100644 --- a/console_cmds.c +++ b/console_cmds.c @@ -529,6 +529,7 @@ DEF_CONSOLE_CMD(ConStatus) { static const char* const stat_str[] = { "inactive", + "authorizing", "authorized", "waiting", "loading map", diff --git a/currency.c b/currency.c index 7bc81139a7..f2658d9d63 100644 --- a/currency.c +++ b/currency.c @@ -168,7 +168,7 @@ void ResetCurrencies(void) StringID* BuildCurrencyDropdown(void) { /* Allow room for all currencies, plus a terminator entry */ - static StringID names[CUSTOM_CURRENCY_ID]; + static StringID names[NUM_CURRENCY + 1]; uint i; /* Add each name */ diff --git a/economy.c b/economy.c index cf4b063f29..c40e658652 100644 --- a/economy.c +++ b/economy.c @@ -362,6 +362,40 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player) MarkWholeScreenDirty(); } +static void ChangeNetworkOwner(PlayerID current_player, PlayerID new_player) +{ +#ifdef ENABLE_NETWORK + if (!_networking) return; + + if (current_player == _local_player) { + _network_playas = new_player; + SetLocalPlayer(new_player); + } + + if (!_network_server) return; + + /* The server has to handle all administrative issues, for example + * updating and notifying all clients of what has happened */ + NetworkClientState *cs; + NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); + + /* The server has just changed from player */ + if (current_player == ci->client_playas) { + ci->client_playas = new_player; + NetworkUpdateClientInfo(NETWORK_SERVER_INDEX); + } + + /* Find all clients that were in control of this company, and mark them as new_player */ + FOR_ALL_CLIENTS(cs) { + ci = DEREF_CLIENT_INFO(cs); + if (current_player == ci->client_playas) { + ci->client_playas = new_player; + NetworkUpdateClientInfo(ci->client_index); + } + } +#endif /* ENABLE_NETWORK */ +} + static void PlayersCheckBankrupt(Player *p) { PlayerID owner; @@ -419,35 +453,9 @@ static void PlayersCheckBankrupt(Player *p) p->bankrupt_asked = 0xFF; p->bankrupt_timeout = 0x456; break; - } else if (owner == _local_player) { - _network_playas = PLAYER_SPECTATOR; - SetLocalPlayer(PLAYER_SPECTATOR); } -#ifdef ENABLE_NETWORK - /* The server has to handle all administrative issues, for example - * updating and notifying all clients of what has happened */ - if (_network_server) { - const NetworkClientState *cs; - NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); - - /* The server has just gone belly-up, mark it as spectator */ - if (owner == ci->client_playas) { - ci->client_playas = PLAYER_SPECTATOR; - NetworkUpdateClientInfo(NETWORK_SERVER_INDEX); - } - - /* Find all clients that were in control of this company, - * and mark them as spectator; broadcast this message to everyone */ - FOR_ALL_CLIENTS(cs) { - ci = DEREF_CLIENT_INFO(cs); - if (ci->client_playas == owner) { - ci->client_playas = PLAYER_SPECTATOR; - NetworkUpdateClientInfo(ci->client_index); - } - } - } -#endif /* ENABLE_NETWORK */ + ChangeNetworkOwner(owner, PLAYER_SPECTATOR); } /* Remove the player */ @@ -1572,6 +1580,7 @@ static void DoAcquireCompany(Player *p) // original code does this a little bit differently pi = p->index; + ChangeNetworkOwner(pi, _current_player); ChangeOwnershipOfPlayerItems(pi, _current_player); if (p->bankrupt_value == 0) { diff --git a/network_data.h b/network_data.h index 589c8ca577..3b6309e7a3 100644 --- a/network_data.h +++ b/network_data.h @@ -49,6 +49,7 @@ typedef struct CommandPacket { typedef enum { STATUS_INACTIVE, + STATUS_AUTHORIZING, // This means that the client is authorizing STATUS_AUTH, // This means that the client is authorized STATUS_MAP_WAIT, // This means that the client is put on hold because someone else is getting the map STATUS_MAP, diff --git a/network_server.c b/network_server.c index b01b8d4c95..e958604bb0 100644 --- a/network_server.c +++ b/network_server.c @@ -215,7 +215,14 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientState *c // uint8: Type of password // - Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD); + Packet *p; + + /* Invalid packet when status is AUTH or higher */ + if (cs->status >= STATUS_AUTH) return; + + cs->status = STATUS_AUTHORIZING; + + p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD); NetworkSend_uint8(p, type); NetworkSend_Packet(p, cs); } @@ -694,7 +701,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD) type = NetworkRecv_uint8(cs, p); NetworkRecv_string(cs, p, password, sizeof(password)); - if (cs->status == STATUS_INACTIVE && type == NETWORK_GAME_PASSWORD) { + if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) { // Check game-password if (strcmp(password, _network_game_info.server_password) != 0) { // Password is invalid @@ -712,7 +719,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD) // Valid password, allow user SEND_COMMAND(PACKET_SERVER_WELCOME)(cs); return; - } else if (cs->status == STATUS_INACTIVE && type == NETWORK_COMPANY_PASSWORD) { + } else if (cs->status == STATUS_AUTHORIZING && type == NETWORK_COMPANY_PASSWORD) { ci = DEREF_CLIENT_INFO(cs); if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) { @@ -1534,6 +1541,12 @@ void NetworkServer_Tick(bool send_frame) IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time); NetworkCloseClient(cs); } + } else if (cs->status == STATUS_INACTIVE) { + int lag = NetworkCalculateLag(cs); + if (lag > 4 * DAY_TICKS) { + IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS); + NetworkCloseClient(cs); + } } if (cs->status >= STATUS_PRE_ACTIVE) {