diff --git a/console_cmds.c b/console_cmds.c index addc9a799a..1da493a22b 100644 --- a/console_cmds.c +++ b/console_cmds.c @@ -756,6 +756,11 @@ DEF_CONSOLE_CMD(ConNetworkConnect) ParseConnectionString(&player, &port, ip); IConsolePrintF(_icolour_def, "Connecting to %s...", ip); + if (port != NULL) { + rport = atoi(port); + IConsolePrintF(_icolour_def, " port: %s", port); + } + if (player != NULL) { _network_playas = atoi(player); IConsolePrintF(_icolour_def, " player-no: %d", _network_playas); @@ -767,10 +772,6 @@ DEF_CONSOLE_CMD(ConNetworkConnect) if (!IsValidPlayer(_network_playas)) return false; } } - if (port != NULL) { - rport = atoi(port); - IConsolePrintF(_icolour_def, " port: %s", port); - } NetworkClientConnectGame(ip, rport); diff --git a/network.c b/network.c index 73d7e7a0ad..50496c91a6 100644 --- a/network.c +++ b/network.c @@ -82,7 +82,7 @@ NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index) { NetworkClientState *cs; - for (cs = _clients; cs != &_clients[MAX_CLIENT_INFO]; cs++) { + for (cs = _clients; cs != endof(_clients); cs++) { if (cs->index == client_index) return cs; } @@ -513,24 +513,25 @@ unsigned long NetworkResolveHost(const char *hostname) return ip; } -// Converts a string to ip/port/player -// Format: IP#player:port -// -// connection_string will be re-terminated to seperate out the hostname, and player and port will -// be set to the player and port strings given by the user, inside the memory area originally -// occupied by connection_string. +/** Converts a string to ip/port/player + * Format: IP#player:port + * + * connection_string will be re-terminated to seperate out the hostname, and player and port will + * be set to the player and port strings given by the user, inside the memory area originally + * occupied by connection_string. */ void ParseConnectionString(const char **player, const char **port, char *connection_string) { char *p; for (p = connection_string; *p != '\0'; p++) { - if (*p == '#') { - *p = '\0'; - *player = ++p; - while (IsValidChar(*p, CS_NUMERAL)) p++; - if (*p == '\0') break; - } else if (*p == ':') { - *port = p + 1; - *p = '\0'; + switch (*p) { + case '#': + *player = p + 1; + *p = '\0'; + break; + case ':': + *port = p + 1; + *p = '\0'; + break; } } } diff --git a/network_client.c b/network_client.c index 22d23720e7..298952a225 100644 --- a/network_client.c +++ b/network_client.c @@ -467,9 +467,18 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP) _frame_counter = _frame_counter_server = _frame_counter_max = NetworkRecv_uint32(MY_CLIENT, p); - _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING; _network_join_kbytes = 0; _network_join_kbytes_total = NetworkRecv_uint32(MY_CLIENT, p) / 1024; + + /* If the network connection has been closed due to loss of connection + * or when _network_join_kbytes_total is 0, the join status window will + * do a division by zero. When the connection is lost, we just return + * that. If kbytes_total is 0, the packet must be malformed as a + * savegame less than 1 kilobyte is practically impossible. */ + if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST; + if (_network_join_kbytes_total == 0) return NETWORK_RECV_STATUS_MALFORMED_PACKET; + + _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING; InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0); // The first packet does not contain any more data diff --git a/network_gui.c b/network_gui.c index 207d93fbe0..c3ab550444 100644 --- a/network_gui.c +++ b/network_gui.c @@ -141,10 +141,17 @@ static int CDECL NGameAllowedSorter(const void *a, const void *b) { const NetworkGameList *cmp1 = *(const NetworkGameList**)a; const NetworkGameList *cmp2 = *(const NetworkGameList**)b; - /* Reverse default as we are interested in compatible clients first */ - int r = cmp2->info.compatible - cmp1->info.compatible; + /* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */ + int r = (cmp1->info.server_revision[0] == '\0') - (cmp2->info.server_revision[0] == '\0'); + + /* Reverse default as we are interested in version-compatible clients first */ + if (r == 0) r = cmp2->info.version_compatible - cmp1->info.version_compatible; + /* The version-compatible ones are then sorted with NewGRF compatible first, incompatible last */ + if (r == 0) r = cmp2->info.compatible - cmp1->info.compatible; + /* Passworded servers should be below unpassworded servers */ if (r == 0) r = cmp1->info.use_password - cmp2->info.use_password; + /* Finally sort on the name of the server */ if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name); return _internal_sort_order ? -r : r; @@ -1409,7 +1416,7 @@ static void NetworkJoinStatusWindowWndProc(Window *w, WindowEvent *e) DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, 14); /* Fallthrough */ default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */ - progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total; + progress = 15 + _network_join_kbytes * (100 - 15) / (_network_join_kbytes_total+1); } /* Draw nice progress bar :) */