13 #include "../stdafx.h" 
   14 #include "../strings_func.h" 
   15 #include "../date_func.h" 
   25 #include "../window_func.h" 
   26 #include "../gfx_func.h" 
   27 #include "../widgets/dropdown_func.h" 
   28 #include "../querystring_gui.h" 
   29 #include "../sortlist_type.h" 
   30 #include "../company_func.h" 
   31 #include "../core/geometry_func.hpp" 
   32 #include "../genworld.h" 
   33 #include "../map_type.h" 
   35 #include "../widgets/network_widget.h" 
   37 #include "table/strings.h" 
   38 #include "../table/sprites.h" 
   40 #include "../stringfilter_type.h" 
   42 #include "../safeguards.h" 
   45 static void ShowNetworkStartServerWindow();
 
   52   STR_NETWORK_START_SERVER_UNADVERTISED,
 
   53   STR_NETWORK_START_SERVER_ADVERTISED,
 
   61   STR_NETWORK_SERVER_LIST_ADVERTISED_NO,
 
   62   STR_NETWORK_SERVER_LIST_ADVERTISED_YES,
 
   66 static StringID _language_dropdown[NETLANG_COUNT + 1] = {STR_NULL};
 
   68 void SortNetworkLanguages()
 
   71   if (_language_dropdown[0] == STR_NULL) {
 
   72     for (
int i = 0; i < NETLANG_COUNT; i++) _language_dropdown[i] = STR_NETWORK_LANG_ANY + i;
 
   77   QSortT(_language_dropdown + 1, NETLANG_COUNT - 1, &StringIDSorter);
 
   90 typedef uint16 ServerListPosition;
 
   91 static const ServerListPosition SLP_INVALID = 0xFFFF;
 
  132     for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
 
  133       child_wid->SetupSmallestSize(w, init_array);
 
  134       this->
smallest_y = 
max(this->
smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
 
  138     for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
 
  139       child_wid->current_x = child_wid->smallest_x;
 
  165       child_wid = child_wid->
next;
 
  174     child_wid = rtl ? this->
tail : this->
head;
 
  175     while (child_wid != NULL) {
 
  181       child_wid = rtl ? child_wid->
prev : child_wid->
next;
 
  189     for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
 
  190       if (!this->
visible[i++]) 
continue;
 
  201     for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
 
  202       if (!this->
visible[i++]) 
continue;
 
  204       if (nwid != NULL) 
return nwid;
 
  281     int r = 
strnatcmp((*a)->info.server_name, (*b)->info.server_name, 
true); 
 
  282     return r == 0 ? (*a)->address.CompareTo((*b)->address) : r;
 
  293     int r = (*a)->info.clients_on - (*b)->info.clients_on;
 
  295     if (r == 0) r = (*a)->info.clients_max - (*b)->info.clients_max;
 
  305     int r = ((*a)->info.map_height) * ((*a)->info.map_width) - ((*b)->info.map_height) * ((*b)->info.map_width);
 
  307     if (r == 0) r = (*a)->info.map_width - (*b)->info.map_width;
 
  314     int r = (*a)->info.game_date - (*b)->info.game_date;
 
  321     int r = (*a)->info.game_date - (*a)->info.start_date - (*b)->info.game_date + (*b)->info.start_date;
 
  332     int r = 
StrEmpty((*a)->info.server_revision) - 
StrEmpty((*b)->info.server_revision);
 
  335     if (r == 0) r = (*b)->info.version_compatible - (*a)->info.version_compatible;
 
  337     if (r == 0) r = (*b)->info.compatible - (*a)->info.compatible;
 
  339     if (r == 0) r = (*a)->info.use_password - (*b)->info.use_password;
 
  366     assert(item != NULL);
 
  367     assert((*item) != NULL);
 
  370     sf.
AddLine((*item)->info.server_name);
 
  386     if (highlight) 
GfxFillRect(nwi_name->
pos_x + 1, y + 1, nwi_info->pos_x + nwi_info->current_x - 2, y + this->resize.step_height - 2, 
PC_GREY);
 
  430         SetDParam(0, ymd_cur.year - ymd_start.year);
 
  454     if (this->
list_pos == SLP_INVALID) 
return; 
 
  508         size->width += padding.width;
 
  509         size->height += padding.height;
 
  514         size->height = 10 * resize->height;
 
  522         size->width = NWidgetScrollbar::GetVerticalDimension().width;
 
  580         this->DrawDetails(r);
 
  620   void DrawDetails(
const Rect &r)
 const 
  630     } 
else if (!sel->
online) {
 
  640       uint16 y = r.top + detail_height + 4;
 
  757           STR_NETWORK_SERVER_LIST_ENTER_IP,
 
  763         ShowNetworkStartServerWindow();
 
  767         if (this->
server != NULL) {
 
  818     if (keycode == WKC_UP || keycode == WKC_DOWN || keycode == WKC_PAGEUP || keycode == WKC_PAGEDOWN || keycode == WKC_HOME || keycode == WKC_END) {
 
  849         default: NOT_REACHED();
 
  862     if (this->
server != NULL) {
 
  863       if (keycode == WKC_DELETE) { 
 
  898     if (!
StrEmpty(str)) NetworkAddServer(str);
 
  912 Listing NetworkGameWindow::last_sorting = {
false, 5};
 
  926 static NWidgetBase *MakeResizableHeader(
int *biggest_index)
 
  928   *biggest_index = max<int>(*biggest_index, 
WID_NG_INFO);
 
  932 static const NWidgetPart _nested_network_game_widgets[] = {
 
  947                       SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
 
  953                       SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
 
  968                         SetDataTip(0x0, STR_NETWORK_SERVER_LIST_CLICK_TO_SELECT_LAST),
 
  979                       SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE, STR_NETWORK_SERVER_LIST_ENTER_NAME_TOOLTIP),
 
 1029   _nested_network_game_widgets, 
lengthof(_nested_network_game_widgets)
 
 1032 void ShowNetworkGameWindow()
 
 1034   static bool first = 
true;
 
 1043       NetworkAddServer(*iter);
 
 1094         size->width += padding.width;
 
 1095         size->height += padding.height;
 
 1113         ShowNetworkGameWindow();
 
 1134             default: NOT_REACHED();
 
 1169         for (uint i = 0; i < 
lengthof(_language_dropdown) - 1; i++) {
 
 1231     for (
const int *widget = raise_widgets; *widget != 
WIDGET_LIST_END; widget++) {
 
 1241     if (str == NULL) 
return;
 
 1246       int32 value = atoi(str);
 
 1249         default: NOT_REACHED();
 
 1260 static const NWidgetPart _nested_network_start_server_window_widgets[] = {
 
 1340 static WindowDesc _network_start_server_window_desc(
 
 1344   _nested_network_start_server_window_widgets, 
lengthof(_nested_network_start_server_window_widgets)
 
 1347 static void ShowNetworkStartServerWindow()
 
 1369   CompanyID NetworkLobbyFindCompanyIndex(byte pos)
 const 
 1373       if (!
StrEmpty(this->company_info[i].company_name)) {
 
 1374         if (pos-- == 0) 
return i;
 
 1390         size->height = 10 * resize->height;
 
 1412         this->DrawDetails(r);
 
 1416         this->DrawMatrix(r);
 
 1438   void DrawMatrix(
const Rect &r)
 const 
 1445     int lock_width      = lock_size.width;
 
 1449     int profit_width      = lock_size.width;
 
 1452     uint text_left   = left  + (rtl ? lock_width + profit_width + 4 : 0);
 
 1453     uint text_right  = right - (rtl ? 0 : lock_width + profit_width + 4);
 
 1454     uint profit_left = rtl ? left : right - profit_width;
 
 1455     uint lock_left   = rtl ? left + profit_width + 2 : right - profit_width - lock_width - 2;
 
 1461       byte 
company = NetworkLobbyFindCompanyIndex(pos);
 
 1462       bool income = 
false;
 
 1463       if (this->company == company) {
 
 1467       DrawString(text_left, text_right, y, this->company_info[company].company_name, TC_BLACK);
 
 1468       if (this->company_info[company].use_password != 0) 
DrawSprite(SPR_LOCK, PAL_NONE, lock_left, y + lock_y_offset);
 
 1471       if (this->company_info[company].income >= 0) income = 
true;
 
 1472       DrawSprite(income ? SPR_PROFIT_LOT : SPR_PROFIT_NEGATIVE, PAL_NONE, profit_left, y + profit_y_offset);
 
 1480   void DrawDetails(
const Rect &r)
 const 
 1489     int y = r.top + detail_height + 4;
 
 1499     SetDParamStr(0, this->company_info[this->company].company_name);
 
 1503     SetDParam(0, this->company_info[this->company].inaugurated_year);
 
 1507     SetDParam(0, this->company_info[this->company].company_value);
 
 1511     SetDParam(0, this->company_info[this->company].money);
 
 1515     SetDParam(0, this->company_info[this->company].income);
 
 1519     SetDParam(0, this->company_info[this->company].performance);
 
 1523     SetDParam(0, this->company_info[this->company].num_vehicle[NETWORK_VEH_TRAIN]);
 
 1524     SetDParam(1, this->company_info[this->company].num_vehicle[NETWORK_VEH_LORRY]);
 
 1525     SetDParam(2, this->company_info[this->company].num_vehicle[NETWORK_VEH_BUS]);
 
 1526     SetDParam(3, this->company_info[this->company].num_vehicle[NETWORK_VEH_SHIP]);
 
 1527     SetDParam(4, this->company_info[this->company].num_vehicle[NETWORK_VEH_PLANE]);
 
 1531     SetDParam(0, this->company_info[this->company].num_station[NETWORK_VEH_TRAIN]);
 
 1532     SetDParam(1, this->company_info[this->company].num_station[NETWORK_VEH_LORRY]);
 
 1533     SetDParam(2, this->company_info[this->company].num_station[NETWORK_VEH_BUS]);
 
 1534     SetDParam(3, this->company_info[this->company].num_station[NETWORK_VEH_SHIP]);
 
 1535     SetDParam(4, this->company_info[this->company].num_station[NETWORK_VEH_PLANE]);
 
 1539     SetDParamStr(0, this->company_info[this->company].clients);
 
 1547         ShowNetworkGameWindow();
 
 1577         memset(this->company_info, 0, 
sizeof(this->company_info));
 
 1588 static const NWidgetPart _nested_network_lobby_window_widgets[] = {
 
 1594     NWidget(
WWT_TEXT, COLOUR_LIGHT_BLUE, 
WID_NL_TEXT), 
SetDataTip(STR_NETWORK_GAME_LOBBY_PREPARE_TO_JOIN, STR_NULL), 
SetResize(1, 0), 
SetPadding(10, 10, 0, 10),
 
 1599         NWidget(
WWT_PANEL, COLOUR_WHITE, 
WID_NL_HEADER), 
SetMinimalSize(146, 0), 
SetResize(1, 0), 
SetFill(1, 0), 
EndContainer(),
 
 1600         NWidget(
WWT_MATRIX, COLOUR_LIGHT_BLUE, 
WID_NL_MATRIX), 
SetMinimalSize(146, 0), 
SetResize(1, 1), 
SetFill(1, 1), 
SetMatrixDataTip(1, 0, STR_NETWORK_GAME_LOBBY_COMPANY_LIST_TOOLTIP), 
SetScrollbar(
WID_NL_SCROLLBAR),
 
 1605       NWidget(
WWT_PANEL, COLOUR_LIGHT_BLUE, 
WID_NL_DETAILS), 
SetMinimalSize(232, 0), 
SetResize(1, 1), 
SetFill(1, 1), 
EndContainer(),
 
 1627 static WindowDesc _network_lobby_window_desc(
 
 1631   _nested_network_lobby_window_widgets, 
lengthof(_nested_network_lobby_window_widgets)
 
 1657   return (lobby != NULL && company < MAX_COMPANIES) ? &lobby->company_info[company] : NULL;
 
 1672 static const NWidgetPart _nested_client_list_popup_widgets[] = {
 
 1680   _nested_client_list_popup_widgets, 
lengthof(_nested_client_list_popup_widgets)
 
 1724   Point desired_location;
 
 1735     action->
name = name;
 
 1736     action->
proc = proc;
 
 1741       sel_index(0), client_id(client_id)
 
 1743     this->desired_location.x = x;
 
 1744     this->desired_location.y = y;
 
 1749       this->
AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, &ClientList_SpeakToClient);
 
 1753       this->
AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, &ClientList_SpeakToCompany);
 
 1755     this->
AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, &ClientList_SpeakToAll);
 
 1760         this->
AddAction(STR_NETWORK_CLIENTLIST_GIVE_MONEY, &ClientList_GiveMoney);
 
 1766       this->
AddAction(STR_NETWORK_CLIENTLIST_KICK, &ClientList_Kick);
 
 1767       this->
AddAction(STR_NETWORK_CLIENTLIST_BAN, &ClientList_Ban);
 
 1776     return this->desired_location;
 
 1795     int sel = this->sel_index;
 
 1816       if (index == this->sel_index || index >= this->
actions.
Length()) 
return;
 
 1818       this->sel_index = index;
 
 1823         if (ci != NULL) this->
actions[index].proc(ci);
 
 1843 static const NWidgetPart _nested_client_list_widgets[] = {
 
 1856   _nested_client_list_widgets, 
lengthof(_nested_client_list_widgets)
 
 1865   uint server_client_width;
 
 1890     num *= this->line_height;
 
 1931     int icon_offset = (this->line_height - icon_size.height) / 2;
 
 1937     uint type_icon_width = this->server_client_width + this->icon_size.width + 
WD_FRAMERECT_LEFT;
 
 1940     uint type_left  = rtl ? right - this->server_client_width : 
left;
 
 1941     uint type_right = rtl ? right : left + this->server_client_width - 1;
 
 1942     uint icon_left  = rtl ? right - type_icon_width + 
WD_FRAMERECT_LEFT : left + this->server_client_width;
 
 1943     uint name_left  = rtl ? left : left + type_icon_width;
 
 1944     uint name_right = rtl ? right - type_icon_width : right;
 
 1950       if (this->selected_item == i++) { 
 
 1958         DrawString(type_left, type_right, y + text_offset, STR_NETWORK_SERVER, colour);
 
 1960         DrawString(type_left, type_right, y + text_offset, STR_NETWORK_CLIENT, colour);
 
 1975     if (this->selected_item != -1) {
 
 1978       int client_no = this->selected_item;
 
 1980         if (client_no == 0) 
break;
 
 1992       this->selected_item = -1;
 
 1998     pt.y -= this->GetWidget<NWidgetBase>(
WID_CL_PANEL)->pos_y;
 
 2005     if (item == this->selected_item) 
return;
 
 2006     this->selected_item = item;
 
 2013 void ShowClientList()
 
 2015   AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0);
 
 2037     DrawString(r.left + 2, r.right - 2, r.top + 20, STR_NETWORK_CONNECTING_1 + _network_join_status, TC_FROMSTRING, 
SA_HOR_CENTER);
 
 2038     switch (_network_join_status) {
 
 2039       case NETWORK_JOIN_STATUS_CONNECTING: 
case NETWORK_JOIN_STATUS_AUTHORIZING:
 
 2040       case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
 
 2043       case NETWORK_JOIN_STATUS_WAITING:
 
 2048       case NETWORK_JOIN_STATUS_DOWNLOADING:
 
 2050         SetDParam(1, _network_join_bytes_total);
 
 2051         DrawString(r.left + 2, r.right - 2, r.top + 20 + 
FONT_HEIGHT_NORMAL, _network_join_bytes_total == 0 ? STR_NETWORK_CONNECTING_DOWNLOADING_1 : STR_NETWORK_CONNECTING_DOWNLOADING_2, TC_FROMSTRING, 
SA_HOR_CENTER);
 
 2052         if (_network_join_bytes_total == 0) {
 
 2058         progress = 15 + _network_join_bytes * (100 - 15) / _network_join_bytes_total;
 
 2062     DrawFrameRect(r.left + 20, r.top + 5, (
int)((this->width - 20) * progress / 100), r.top + 15, COLOUR_MAUVE, FR_NONE);
 
 2073     for (uint i = 0; i < NETWORK_JOIN_STATUS_END; i++) {
 
 2096       ShowNetworkGameWindow();
 
 2104       ShowNetworkGameWindow();
 
 2108     switch (this->password_type) {
 
 2111       default: NOT_REACHED();
 
 2116 static const NWidgetPart _nested_network_join_status_window_widgets[] = {
 
 2129 static WindowDesc _network_join_status_window_desc(
 
 2133   _nested_network_join_status_window_widgets, 
lengthof(_nested_network_join_status_window_widgets)
 
 2136 void ShowJoinStatusWindow()
 
 2145   if (w == NULL) 
return;
 
 2146   w->password_type = npt;
 
 2150     default: NOT_REACHED();
 
 2199 static const NWidgetPart _nested_network_company_password_window_widgets[] = {
 
 2213                       SetDataTip(STR_COMPANY_PASSWORD_MAKE_DEFAULT, STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP),
 
 2223 static WindowDesc _network_company_password_window_desc(
 
 2227   _nested_network_company_password_window_widgets, 
lengthof(_nested_network_company_password_window_widgets)
 
 2230 void ShowNetworkCompanyPasswordWindow(
Window *parent)