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)