OpenTTD
network_gui.cpp
Go to the documentation of this file.
1 /* $Id: network_gui.cpp 27893 2017-08-13 18:38:42Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #ifdef ENABLE_NETWORK
13 #include "../stdafx.h"
14 #include "../strings_func.h"
15 #include "../date_func.h"
16 #include "../fios.h"
17 #include "network_client.h"
18 #include "network_gui.h"
19 #include "network_gamelist.h"
20 #include "network.h"
21 #include "network_base.h"
22 #include "network_content.h"
23 #include "../gui.h"
24 #include "network_udp.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"
34 
35 #include "../widgets/network_widget.h"
36 
37 #include "table/strings.h"
38 #include "../table/sprites.h"
39 
40 #include "../stringfilter_type.h"
41 
42 #include "../safeguards.h"
43 
44 
45 static void ShowNetworkStartServerWindow();
46 static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
47 
52  STR_NETWORK_START_SERVER_UNADVERTISED,
53  STR_NETWORK_START_SERVER_ADVERTISED,
55 };
56 
61  STR_NETWORK_SERVER_LIST_ADVERTISED_NO,
62  STR_NETWORK_SERVER_LIST_ADVERTISED_YES,
64 };
65 
66 static StringID _language_dropdown[NETLANG_COUNT + 1] = {STR_NULL};
67 
68 void SortNetworkLanguages()
69 {
70  /* Init the strings */
71  if (_language_dropdown[0] == STR_NULL) {
72  for (int i = 0; i < NETLANG_COUNT; i++) _language_dropdown[i] = STR_NETWORK_LANG_ANY + i;
73  _language_dropdown[NETLANG_COUNT] = INVALID_STRING_ID;
74  }
75 
76  /* Sort the strings (we don't move 'any' and the 'invalid' one) */
77  QSortT(_language_dropdown + 1, NETLANG_COUNT - 1, &StringIDSorter);
78 }
79 
85 {
87 }
88 
90 typedef uint16 ServerListPosition;
91 static const ServerListPosition SLP_INVALID = 0xFFFF;
92 
95  static const uint MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER = 150;
96  bool visible[6];
97 public:
99  {
100  NWidgetLeaf *leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME_TOOLTIP);
101  leaf->SetResize(1, 0);
102  leaf->SetFill(1, 0);
103  this->Add(leaf);
104 
105  this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_CLIENTS, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION_TOOLTIP));
106  this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_MAPSIZE, STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION, STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION_TOOLTIP));
107  this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_DATE, STR_NETWORK_SERVER_LIST_DATE_CAPTION, STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP));
108  this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_YEARS, STR_NETWORK_SERVER_LIST_YEARS_CAPTION, STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP));
109 
110  leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_INFO, STR_EMPTY, STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP);
111  leaf->SetMinimalSize(14 + GetSpriteSize(SPR_LOCK).width + GetSpriteSize(SPR_BLOT).width + GetSpriteSize(SPR_FLAGS_BASE).width, 12);
112  leaf->SetFill(0, 1);
113  this->Add(leaf);
114 
115  /* First and last are always visible, the rest is implicitly zeroed */
116  this->visible[0] = true;
117  *lastof(this->visible) = true;
118  }
119 
120  void SetupSmallestSize(Window *w, bool init_array)
121  {
122  /* Oh yeah, we ought to be findable! */
123  w->nested_array[WID_NG_HEADER] = this;
124 
125  this->smallest_y = 0; // Biggest child.
126  this->fill_x = 1;
127  this->fill_y = 0;
128  this->resize_x = 1; // We only resize in this direction
129  this->resize_y = 0; // We never resize in this direction
130 
131  /* First initialise some variables... */
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);
135  }
136 
137  /* ... then in a second pass make sure the 'current' sizes are set. Won't change for most widgets. */
138  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
139  child_wid->current_x = child_wid->smallest_x;
140  child_wid->current_y = this->smallest_y;
141  }
142 
143  this->smallest_x = this->head->smallest_x + this->tail->smallest_x; // First and last are always shown, rest not
144  }
145 
146  void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
147  {
148  assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
149 
150  this->pos_x = x;
151  this->pos_y = y;
152  this->current_x = given_width;
153  this->current_y = given_height;
154 
155  given_width -= this->tail->smallest_x;
156  NWidgetBase *child_wid = this->head->next;
157  /* The first and last widget are always visible, determine which other should be visible */
158  for (uint i = 1; i < lengthof(this->visible) - 1; i++) {
159  if (given_width > MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER + child_wid->smallest_x && this->visible[i - 1]) {
160  this->visible[i] = true;
161  given_width -= child_wid->smallest_x;
162  } else {
163  this->visible[i] = false;
164  }
165  child_wid = child_wid->next;
166  }
167 
168  /* All remaining space goes to the first (name) widget */
169  this->head->current_x = given_width;
170 
171  /* Now assign the widgets to their rightful place */
172  uint position = 0; // Place to put next child relative to origin of the container.
173  uint i = rtl ? lengthof(this->visible) - 1 : 0;
174  child_wid = rtl ? this->tail : this->head;
175  while (child_wid != NULL) {
176  if (this->visible[i]) {
177  child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
178  position += child_wid->current_x;
179  }
180 
181  child_wid = rtl ? child_wid->prev : child_wid->next;
182  i += rtl ? -1 : 1;
183  }
184  }
185 
186  /* virtual */ void Draw(const Window *w)
187  {
188  int i = 0;
189  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
190  if (!this->visible[i++]) continue;
191 
192  child_wid->Draw(w);
193  }
194  }
195 
196  /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
197  {
198  if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
199 
200  int i = 0;
201  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
202  if (!this->visible[i++]) continue;
203  NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
204  if (nwid != NULL) return nwid;
205  }
206  return NULL;
207  }
208 
215  {
216  assert((uint)(widget - WID_NG_NAME) < lengthof(this->visible));
217  return this->visible[widget - WID_NG_NAME];
218  }
219 };
220 
221 class NetworkGameWindow : public Window {
222 protected:
223  /* Runtime saved values */
224  static Listing last_sorting;
225 
226  /* Constants for sorting servers */
227  static GUIGameServerList::SortFunction * const sorter_funcs[];
228  static GUIGameServerList::FilterFunction * const filter_funcs[];
229 
233  ServerListPosition list_pos;
237 
241 
248  {
249  if (!this->servers.NeedRebuild()) return;
250 
251  /* Create temporary array of games to use for listing */
252  this->servers.Clear();
253 
254  for (NetworkGameList *ngl = _network_game_list; ngl != NULL; ngl = ngl->next) {
255  *this->servers.Append() = ngl;
256  }
257 
258  /* Apply the filter condition immediately, if a search string has been provided. */
259  StringFilter sf;
260  sf.SetFilterTerm(this->filter_editbox.text.buf);
261 
262  if (!sf.IsEmpty()) {
263  this->servers.SetFilterState(true);
264  this->servers.Filter(sf);
265  } else {
266  this->servers.SetFilterState(false);
267  }
268 
269  this->servers.Compact();
270  this->servers.RebuildDone();
271  this->vscroll->SetCount(this->servers.Length());
272 
273  /* Sort the list of network games as requested. */
274  this->servers.Sort();
275  this->UpdateListPos();
276  }
277 
279  static int CDECL NGameNameSorter(NetworkGameList * const *a, NetworkGameList * const *b)
280  {
281  int r = strnatcmp((*a)->info.server_name, (*b)->info.server_name, true); // Sort by name (natural sorting).
282  return r == 0 ? (*a)->address.CompareTo((*b)->address) : r;
283  }
284 
290  static int CDECL NGameClientSorter(NetworkGameList * const *a, NetworkGameList * const *b)
291  {
292  /* Reverse as per default we are interested in most-clients first */
293  int r = (*a)->info.clients_on - (*b)->info.clients_on;
294 
295  if (r == 0) r = (*a)->info.clients_max - (*b)->info.clients_max;
296  if (r == 0) r = NGameNameSorter(a, b);
297 
298  return r;
299  }
300 
302  static int CDECL NGameMapSizeSorter(NetworkGameList * const *a, NetworkGameList * const *b)
303  {
304  /* Sort by the area of the map. */
305  int r = ((*a)->info.map_height) * ((*a)->info.map_width) - ((*b)->info.map_height) * ((*b)->info.map_width);
306 
307  if (r == 0) r = (*a)->info.map_width - (*b)->info.map_width;
308  return (r != 0) ? r : NGameClientSorter(a, b);
309  }
310 
312  static int CDECL NGameDateSorter(NetworkGameList * const *a, NetworkGameList * const *b)
313  {
314  int r = (*a)->info.game_date - (*b)->info.game_date;
315  return (r != 0) ? r : NGameClientSorter(a, b);
316  }
317 
319  static int CDECL NGameYearsSorter(NetworkGameList * const *a, NetworkGameList * const *b)
320  {
321  int r = (*a)->info.game_date - (*a)->info.start_date - (*b)->info.game_date + (*b)->info.start_date;
322  return (r != 0) ? r : NGameDateSorter(a, b);
323  }
324 
329  static int CDECL NGameAllowedSorter(NetworkGameList * const *a, NetworkGameList * const *b)
330  {
331  /* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */
332  int r = StrEmpty((*a)->info.server_revision) - StrEmpty((*b)->info.server_revision);
333 
334  /* Reverse default as we are interested in version-compatible clients first */
335  if (r == 0) r = (*b)->info.version_compatible - (*a)->info.version_compatible;
336  /* The version-compatible ones are then sorted with NewGRF compatible first, incompatible last */
337  if (r == 0) r = (*b)->info.compatible - (*a)->info.compatible;
338  /* Passworded servers should be below unpassworded servers */
339  if (r == 0) r = (*a)->info.use_password - (*b)->info.use_password;
340  /* Finally sort on the number of clients of the server */
341  if (r == 0) r = -NGameClientSorter(a, b);
342 
343  return r;
344  }
345 
348  {
349  if (this->servers.Sort()) this->UpdateListPos();
350  }
351 
354  {
355  this->list_pos = SLP_INVALID;
356  for (uint i = 0; i != this->servers.Length(); i++) {
357  if (this->servers[i] == this->server) {
358  this->list_pos = i;
359  break;
360  }
361  }
362  }
363 
364  static bool CDECL NGameSearchFilter(NetworkGameList * const *item, StringFilter &sf)
365  {
366  assert(item != NULL);
367  assert((*item) != NULL);
368 
369  sf.ResetState();
370  sf.AddLine((*item)->info.server_name);
371  return sf.GetState();
372  }
373 
380  void DrawServerLine(const NetworkGameList *cur_item, uint y, bool highlight) const
381  {
382  const NWidgetBase *nwi_name = this->GetWidget<NWidgetBase>(WID_NG_NAME);
383  const NWidgetBase *nwi_info = this->GetWidget<NWidgetBase>(WID_NG_INFO);
384 
385  /* show highlighted item with a different colour */
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);
387 
388  /* offsets to vertically centre text and icons */
389  int text_y_offset = (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2 + 1;
390  int icon_y_offset = (this->resize.step_height - GetSpriteSize(SPR_BLOT).height) / 2;
391 
392  DrawString(nwi_name->pos_x + WD_FRAMERECT_LEFT, nwi_name->pos_x + nwi_name->current_x - WD_FRAMERECT_RIGHT, y + text_y_offset, cur_item->info.server_name, TC_BLACK);
393 
394  /* only draw details if the server is online */
395  if (cur_item->online) {
396  const NWidgetServerListHeader *nwi_header = this->GetWidget<NWidgetServerListHeader>(WID_NG_HEADER);
397 
398  if (nwi_header->IsWidgetVisible(WID_NG_CLIENTS)) {
399  const NWidgetBase *nwi_clients = this->GetWidget<NWidgetBase>(WID_NG_CLIENTS);
400  SetDParam(0, cur_item->info.clients_on);
401  SetDParam(1, cur_item->info.clients_max);
402  SetDParam(2, cur_item->info.companies_on);
403  SetDParam(3, cur_item->info.companies_max);
404  DrawString(nwi_clients->pos_x, nwi_clients->pos_x + nwi_clients->current_x - 1, y + text_y_offset, STR_NETWORK_SERVER_LIST_GENERAL_ONLINE, TC_FROMSTRING, SA_HOR_CENTER);
405  }
406 
407  if (nwi_header->IsWidgetVisible(WID_NG_MAPSIZE)) {
408  /* map size */
409  const NWidgetBase *nwi_mapsize = this->GetWidget<NWidgetBase>(WID_NG_MAPSIZE);
410  SetDParam(0, cur_item->info.map_width);
411  SetDParam(1, cur_item->info.map_height);
412  DrawString(nwi_mapsize->pos_x, nwi_mapsize->pos_x + nwi_mapsize->current_x - 1, y + text_y_offset, STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT, TC_FROMSTRING, SA_HOR_CENTER);
413  }
414 
415  if (nwi_header->IsWidgetVisible(WID_NG_DATE)) {
416  /* current date */
417  const NWidgetBase *nwi_date = this->GetWidget<NWidgetBase>(WID_NG_DATE);
418  YearMonthDay ymd;
419  ConvertDateToYMD(cur_item->info.game_date, &ymd);
420  SetDParam(0, ymd.year);
421  DrawString(nwi_date->pos_x, nwi_date->pos_x + nwi_date->current_x - 1, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER);
422  }
423 
424  if (nwi_header->IsWidgetVisible(WID_NG_YEARS)) {
425  /* number of years the game is running */
426  const NWidgetBase *nwi_years = this->GetWidget<NWidgetBase>(WID_NG_YEARS);
427  YearMonthDay ymd_cur, ymd_start;
428  ConvertDateToYMD(cur_item->info.game_date, &ymd_cur);
429  ConvertDateToYMD(cur_item->info.start_date, &ymd_start);
430  SetDParam(0, ymd_cur.year - ymd_start.year);
431  DrawString(nwi_years->pos_x, nwi_years->pos_x + nwi_years->current_x - 1, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER);
432  }
433 
434  /* draw a lock if the server is password protected */
435  if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, nwi_info->pos_x + this->lock_offset, y + icon_y_offset - 1);
436 
437  /* draw red or green icon, depending on compatibility with server */
438  DrawSprite(SPR_BLOT, (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), nwi_info->pos_x + this->blot_offset, y + icon_y_offset);
439 
440  /* draw flag according to server language */
441  DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, nwi_info->pos_x + this->flag_offset, y + icon_y_offset);
442  }
443  }
444 
453  {
454  if (this->list_pos == SLP_INVALID) return; // no server selected
455  this->vscroll->ScrollTowards(this->list_pos);
456  }
457 
458 public:
459  NetworkGameWindow(WindowDesc *desc) : Window(desc), name_editbox(NETWORK_CLIENT_NAME_LENGTH), filter_editbox(120)
460  {
461  this->list_pos = SLP_INVALID;
462  this->server = NULL;
463 
464  this->lock_offset = 5;
465  this->blot_offset = this->lock_offset + 3 + GetSpriteSize(SPR_LOCK).width;
466  this->flag_offset = this->blot_offset + 2 + GetSpriteSize(SPR_BLOT).width;
467 
468  this->CreateNestedTree();
469  this->vscroll = this->GetScrollbar(WID_NG_SCROLLBAR);
470  this->FinishInitNested(WN_NETWORK_WINDOW_GAME);
471 
472  this->querystrings[WID_NG_CLIENT] = &this->name_editbox;
473  this->name_editbox.text.Assign(_settings_client.network.client_name);
474 
475  this->querystrings[WID_NG_FILTER] = &this->filter_editbox;
476  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
477  this->SetFocusedWidget(WID_NG_FILTER);
478 
480  this->server = this->last_joined;
481  if (this->last_joined != NULL) NetworkUDPQueryServer(this->last_joined->address);
482 
483  this->servers.SetListing(this->last_sorting);
484  this->servers.SetSortFuncs(this->sorter_funcs);
485  this->servers.SetFilterFuncs(this->filter_funcs);
486  this->servers.ForceRebuild();
487  }
488 
490  {
491  this->last_sorting = this->servers.GetListing();
492  }
493 
494  virtual void SetStringParameters(int widget) const
495  {
496  switch (widget) {
497  case WID_NG_CONN_BTN:
499  break;
500  }
501  }
502 
503  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
504  {
505  switch (widget) {
506  case WID_NG_CONN_BTN:
508  size->width += padding.width;
509  size->height += padding.height;
510  break;
511 
512  case WID_NG_MATRIX:
513  resize->height = WD_MATRIX_TOP + max(GetSpriteSize(SPR_BLOT).height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM;
514  size->height = 10 * resize->height;
515  break;
516 
517  case WID_NG_LASTJOINED:
518  size->height = WD_MATRIX_TOP + max(GetSpriteSize(SPR_BLOT).height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM;
519  break;
520 
522  size->width = NWidgetScrollbar::GetVerticalDimension().width;
523  break;
524 
525  case WID_NG_NAME:
526  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
527  break;
528 
529  case WID_NG_CLIENTS:
530  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
535  *size = maxdim(*size, GetStringBoundingBox(STR_NETWORK_SERVER_LIST_GENERAL_ONLINE));
536  break;
537 
538  case WID_NG_MAPSIZE:
539  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
542  *size = maxdim(*size, GetStringBoundingBox(STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT));
543  break;
544 
545  case WID_NG_DATE:
546  case WID_NG_YEARS:
547  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
548  SetDParamMaxValue(0, 5);
549  *size = maxdim(*size, GetStringBoundingBox(STR_JUST_INT));
550  break;
551 
553  size->height = 20 + 12 * FONT_HEIGHT_NORMAL;
554  break;
555  }
556  }
557 
558  virtual void DrawWidget(const Rect &r, int widget) const
559  {
560  switch (widget) {
561  case WID_NG_MATRIX: {
562  uint16 y = r.top;
563 
564  const int max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), (int)this->servers.Length());
565 
566  for (int i = this->vscroll->GetPosition(); i < max; ++i) {
567  const NetworkGameList *ngl = this->servers[i];
568  this->DrawServerLine(ngl, y, ngl == this->server);
569  y += this->resize.step_height;
570  }
571  break;
572  }
573 
574  case WID_NG_LASTJOINED:
575  /* Draw the last joined server, if any */
576  if (this->last_joined != NULL) this->DrawServerLine(this->last_joined, r.top, this->last_joined == this->server);
577  break;
578 
579  case WID_NG_DETAILS:
580  this->DrawDetails(r);
581  break;
582 
583  case WID_NG_NAME:
584  case WID_NG_CLIENTS:
585  case WID_NG_MAPSIZE:
586  case WID_NG_DATE:
587  case WID_NG_YEARS:
588  case WID_NG_INFO:
589  if (widget - WID_NG_NAME == this->servers.SortType()) this->DrawSortButtonState(widget, this->servers.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
590  break;
591  }
592  }
593 
594 
595  virtual void OnPaint()
596  {
597  if (this->servers.NeedRebuild()) {
598  this->BuildGUINetworkGameList();
599  }
600  if (this->servers.NeedResort()) {
601  this->SortNetworkGameList();
602  }
603 
604  NetworkGameList *sel = this->server;
605  /* 'Refresh' button invisible if no server selected */
606  this->SetWidgetDisabledState(WID_NG_REFRESH, sel == NULL);
607  /* 'Join' button disabling conditions */
608  this->SetWidgetDisabledState(WID_NG_JOIN, sel == NULL || // no Selected Server
609  !sel->online || // Server offline
610  sel->info.clients_on >= sel->info.clients_max || // Server full
611  !sel->info.compatible); // Revision mismatch
612 
613  /* 'NewGRF Settings' button invisible if no NewGRF is used */
614  this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_SEL)->SetDisplayedPlane(sel == NULL || !sel->online || sel->info.grfconfig == NULL);
615  this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_MISSING_SEL)->SetDisplayedPlane(sel == NULL || !sel->online || sel->info.grfconfig == NULL || !sel->info.version_compatible || sel->info.compatible);
616 
617  this->DrawWidgets();
618  }
619 
620  void DrawDetails(const Rect &r) const
621  {
622  NetworkGameList *sel = this->server;
623 
624  const int detail_height = 6 + 8 + 6 + 3 * FONT_HEIGHT_NORMAL;
625 
626  /* Draw the right menu */
627  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + detail_height - 1, PC_DARK_BLUE);
628  if (sel == NULL) {
629  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 6 + 4 + FONT_HEIGHT_NORMAL, STR_NETWORK_SERVER_LIST_GAME_INFO, TC_FROMSTRING, SA_HOR_CENTER);
630  } else if (!sel->online) {
631  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 6 + 4 + FONT_HEIGHT_NORMAL, sel->info.server_name, TC_ORANGE, SA_HOR_CENTER); // game name
632 
633  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + detail_height + 4, STR_NETWORK_SERVER_LIST_SERVER_OFFLINE, TC_FROMSTRING, SA_HOR_CENTER); // server offline
634  } else { // show game info
635 
636  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 6, STR_NETWORK_SERVER_LIST_GAME_INFO, TC_FROMSTRING, SA_HOR_CENTER);
637  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 6 + 4 + FONT_HEIGHT_NORMAL, sel->info.server_name, TC_ORANGE, SA_HOR_CENTER); // game name
638  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 6 + 8 + 2 * FONT_HEIGHT_NORMAL, sel->info.map_name, TC_BLACK, SA_HOR_CENTER); // map name
639 
640  uint16 y = r.top + detail_height + 4;
641 
642  SetDParam(0, sel->info.clients_on);
643  SetDParam(1, sel->info.clients_max);
644  SetDParam(2, sel->info.companies_on);
645  SetDParam(3, sel->info.companies_max);
646  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CLIENTS);
647  y += FONT_HEIGHT_NORMAL;
648 
649  SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
650  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_LANGUAGE); // server language
651  y += FONT_HEIGHT_NORMAL;
652 
653  SetDParam(0, STR_CHEAT_SWITCH_CLIMATE_TEMPERATE_LANDSCAPE + sel->info.map_set);
654  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_LANDSCAPE); // landscape
655  y += FONT_HEIGHT_NORMAL;
656 
657  SetDParam(0, sel->info.map_width);
658  SetDParam(1, sel->info.map_height);
659  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_MAP_SIZE); // map size
660  y += FONT_HEIGHT_NORMAL;
661 
663  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_VERSION); // server version
664  y += FONT_HEIGHT_NORMAL;
665 
667  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_ADDRESS); // server address
668  y += FONT_HEIGHT_NORMAL;
669 
670  SetDParam(0, sel->info.start_date);
671  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_START_DATE); // start date
672  y += FONT_HEIGHT_NORMAL;
673 
674  SetDParam(0, sel->info.game_date);
675  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CURRENT_DATE); // current date
676  y += FONT_HEIGHT_NORMAL;
677 
678  y += WD_PAR_VSEP_NORMAL;
679 
680  if (!sel->info.compatible) {
681  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, sel->info.version_compatible ? STR_NETWORK_SERVER_LIST_GRF_MISMATCH : STR_NETWORK_SERVER_LIST_VERSION_MISMATCH, TC_FROMSTRING, SA_HOR_CENTER); // server mismatch
682  } else if (sel->info.clients_on == sel->info.clients_max) {
683  /* Show: server full, when clients_on == max_clients */
684  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_FULL, TC_FROMSTRING, SA_HOR_CENTER); // server full
685  } else if (sel->info.use_password) {
686  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_PASSWORD, TC_FROMSTRING, SA_HOR_CENTER); // password warning
687  }
688  }
689  }
690 
691  virtual void OnClick(Point pt, int widget, int click_count)
692  {
693  switch (widget) {
694  case WID_NG_CANCEL: // Cancel button
696  break;
697 
698  case WID_NG_CONN_BTN: // 'Connection' droplist
699  ShowDropDownMenu(this, _lan_internet_types_dropdown, _settings_client.network.lan_internet, WID_NG_CONN_BTN, 0, 0); // do it for widget WID_NSS_CONN_BTN
700  break;
701 
702  case WID_NG_NAME: // Sort by name
703  case WID_NG_CLIENTS: // Sort by connected clients
704  case WID_NG_MAPSIZE: // Sort by map size
705  case WID_NG_DATE: // Sort by date
706  case WID_NG_YEARS: // Sort by years
707  case WID_NG_INFO: // Connectivity (green dot)
708  if (this->servers.SortType() == widget - WID_NG_NAME) {
709  this->servers.ToggleSortOrder();
710  if (this->list_pos != SLP_INVALID) this->list_pos = this->servers.Length() - this->list_pos - 1;
711  } else {
712  this->servers.SetSortType(widget - WID_NG_NAME);
713  this->servers.ForceResort();
714  this->SortNetworkGameList();
715  }
716  this->ScrollToSelectedServer();
717  this->SetDirty();
718  break;
719 
720  case WID_NG_MATRIX: { // Show available network games
721  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NG_MATRIX);
722  this->server = (id_v < this->servers.Length()) ? this->servers[id_v] : NULL;
723  this->list_pos = (server == NULL) ? SLP_INVALID : id_v;
724  this->SetDirty();
725 
726  /* FIXME the disabling should go into some InvalidateData, which is called instead of the SetDirty */
727  if (click_count > 1 && !this->IsWidgetDisabled(WID_NG_JOIN)) this->OnClick(pt, WID_NG_JOIN, 1);
728  break;
729  }
730 
731  case WID_NG_LASTJOINED: {
732  if (this->last_joined != NULL) {
733  this->server = this->last_joined;
734 
735  /* search the position of the newly selected server */
736  this->UpdateListPos();
737  this->ScrollToSelectedServer();
738  this->SetDirty();
739 
740  /* FIXME the disabling should go into some InvalidateData, which is called instead of the SetDirty */
741  if (click_count > 1 && !this->IsWidgetDisabled(WID_NG_JOIN)) this->OnClick(pt, WID_NG_JOIN, 1);
742  }
743  break;
744  }
745 
746  case WID_NG_FIND: // Find server automatically
748  case 0: NetworkUDPSearchGame(); break;
749  case 1: NetworkUDPQueryMasterServer(); break;
750  }
751  break;
752 
753  case WID_NG_ADD: // Add a server
756  STR_JUST_RAW_STRING,
757  STR_NETWORK_SERVER_LIST_ENTER_IP,
758  NETWORK_HOSTNAME_LENGTH, // maximum number of characters including '\0'
760  break;
761 
762  case WID_NG_START: // Start server
763  ShowNetworkStartServerWindow();
764  break;
765 
766  case WID_NG_JOIN: // Join Game
767  if (this->server != NULL) {
768  seprintf(_settings_client.network.last_host, lastof(_settings_client.network.last_host), "%s", this->server->address.GetHostname());
770  ShowNetworkLobbyWindow(this->server);
771  }
772  break;
773 
774  case WID_NG_REFRESH: // Refresh
775  if (this->server != NULL) NetworkUDPQueryServer(this->server->address);
776  break;
777 
778  case WID_NG_NEWGRF: // NewGRF Settings
779  if (this->server != NULL) ShowNewGRFSettings(false, false, false, &this->server->info.grfconfig);
780  break;
781 
782  case WID_NG_NEWGRF_MISSING: // Find missing content online
783  if (this->server != NULL) ShowMissingContentWindow(this->server->info.grfconfig);
784  break;
785  }
786  }
787 
788  virtual void OnDropdownSelect(int widget, int index)
789  {
790  switch (widget) {
791  case WID_NG_CONN_BTN:
793  break;
794 
795  default:
796  NOT_REACHED();
797  }
798 
799  this->SetDirty();
800  }
801 
807  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
808  {
809  this->servers.ForceRebuild();
810  this->SetDirty();
811  }
812 
813  virtual EventState OnKeyPress(WChar key, uint16 keycode)
814  {
815  EventState state = ES_NOT_HANDLED;
816 
817  /* handle up, down, pageup, pagedown, home and end */
818  if (keycode == WKC_UP || keycode == WKC_DOWN || keycode == WKC_PAGEUP || keycode == WKC_PAGEDOWN || keycode == WKC_HOME || keycode == WKC_END) {
819  if (this->servers.Length() == 0) return ES_HANDLED;
820  switch (keycode) {
821  case WKC_UP:
822  /* scroll up by one */
823  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
824  if (this->list_pos > 0) this->list_pos--;
825  break;
826  case WKC_DOWN:
827  /* scroll down by one */
828  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
829  if (this->list_pos < this->servers.Length() - 1) this->list_pos++;
830  break;
831  case WKC_PAGEUP:
832  /* scroll up a page */
833  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
834  this->list_pos = (this->list_pos < this->vscroll->GetCapacity()) ? 0 : this->list_pos - this->vscroll->GetCapacity();
835  break;
836  case WKC_PAGEDOWN:
837  /* scroll down a page */
838  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
839  this->list_pos = min(this->list_pos + this->vscroll->GetCapacity(), (int)this->servers.Length() - 1);
840  break;
841  case WKC_HOME:
842  /* jump to beginning */
843  this->list_pos = 0;
844  break;
845  case WKC_END:
846  /* jump to end */
847  this->list_pos = this->servers.Length() - 1;
848  break;
849  default: NOT_REACHED();
850  }
851 
852  this->server = this->servers[this->list_pos];
853 
854  /* Scroll to the new server if it is outside the current range. */
855  this->ScrollToSelectedServer();
856 
857  /* redraw window */
858  this->SetDirty();
859  return ES_HANDLED;
860  }
861 
862  if (this->server != NULL) {
863  if (keycode == WKC_DELETE) { // Press 'delete' to remove servers
864  NetworkGameListRemoveItem(this->server);
865  if (this->server == this->last_joined) this->last_joined = NULL;
866  this->server = NULL;
867  this->list_pos = SLP_INVALID;
868  }
869  }
870 
871  return state;
872  }
873 
874  virtual void OnEditboxChanged(int wid)
875  {
876  switch (wid) {
877  case WID_NG_FILTER: {
878  this->servers.ForceRebuild();
879  this->BuildGUINetworkGameList();
880  this->ScrollToSelectedServer();
881  this->SetDirty();
882  break;
883  }
884 
885  case WID_NG_CLIENT:
886  /* Make sure the name does not start with a space, so TAB completion works */
887  if (!StrEmpty(this->name_editbox.text.buf) && this->name_editbox.text.buf[0] != ' ') {
889  } else {
891  }
892  break;
893  }
894  }
895 
896  virtual void OnQueryTextFinished(char *str)
897  {
898  if (!StrEmpty(str)) NetworkAddServer(str);
899  }
900 
901  virtual void OnResize()
902  {
903  this->vscroll->SetCapacityFromWidget(this, WID_NG_MATRIX);
904  }
905 
906  virtual void OnTick()
907  {
909  }
910 };
911 
912 Listing NetworkGameWindow::last_sorting = {false, 5};
913 GUIGameServerList::SortFunction * const NetworkGameWindow::sorter_funcs[] = {
914  &NGameNameSorter,
915  &NGameClientSorter,
916  &NGameMapSizeSorter,
917  &NGameDateSorter,
918  &NGameYearsSorter,
919  &NGameAllowedSorter
920 };
921 
922 GUIGameServerList::FilterFunction * const NetworkGameWindow::filter_funcs[] = {
923  &NGameSearchFilter
924 };
925 
926 static NWidgetBase *MakeResizableHeader(int *biggest_index)
927 {
928  *biggest_index = max<int>(*biggest_index, WID_NG_INFO);
929  return new NWidgetServerListHeader();
930 }
931 
932 static const NWidgetPart _nested_network_game_widgets[] = {
933  /* TOP */
935  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
936  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_NETWORK_SERVER_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
937  NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
938  EndContainer(),
939  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_MAIN),
940  NWidget(NWID_VERTICAL), SetPIP(10, 7, 0),
941  NWidget(NWID_HORIZONTAL), SetPIP(10, 7, 10),
942  /* LEFT SIDE */
943  NWidget(NWID_VERTICAL), SetPIP(0, 7, 0),
944  NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
945  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CONNECTION), SetDataTip(STR_NETWORK_SERVER_LIST_ADVERTISED, STR_NULL),
946  NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NG_CONN_BTN),
947  SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
948  NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
949  EndContainer(),
950  NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
951  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_FILTER_LABEL), SetDataTip(STR_LIST_FILTER_TITLE, STR_NULL),
952  NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_FILTER), SetMinimalSize(251, 12), SetFill(1, 0), SetResize(1, 0),
953  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
954  EndContainer(),
957  NWidgetFunction(MakeResizableHeader),
958  NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, WID_NG_MATRIX), SetResize(1, 1), SetFill(1, 0),
959  SetMatrixDataTip(1, 0, STR_NETWORK_SERVER_LIST_CLICK_GAME_TO_SELECT), SetScrollbar(WID_NG_SCROLLBAR),
960  EndContainer(),
961  NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NG_SCROLLBAR),
962  EndContainer(),
964  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED_LABEL), SetFill(1, 0),
965  SetDataTip(STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER, STR_NULL), SetResize(1, 0),
967  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED), SetFill(1, 0), SetResize(1, 0),
968  SetDataTip(0x0, STR_NETWORK_SERVER_LIST_CLICK_TO_SELECT_LAST),
969  EndContainer(),
970  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_LASTJOINED_SPACER), SetFill(0, 0),
971  EndContainer(),
972  EndContainer(),
973  EndContainer(),
974  /* RIGHT SIDE */
975  NWidget(NWID_VERTICAL), SetPIP(0, 7, 0),
976  NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
977  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CLIENT_LABEL), SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME, STR_NULL),
978  NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_CLIENT), SetMinimalSize(151, 12), SetFill(1, 0), SetResize(1, 0),
979  SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE, STR_NETWORK_SERVER_LIST_ENTER_NAME_TOOLTIP),
980  EndContainer(),
981  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_DETAILS),
983  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_DETAILS_SPACER), SetMinimalSize(140, 155), SetResize(0, 1), SetFill(1, 1), // Make sure it's at least this wide
986  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF_MISSING), SetFill(1, 0), SetDataTip(STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_BUTTON, STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_TOOLTIP),
987  NWidget(NWID_SPACER), SetFill(1, 0),
988  EndContainer(),
989  EndContainer(),
991  NWidget(NWID_SPACER), SetFill(1, 0),
992  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NG_NEWGRF_SEL),
993  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF), SetFill(1, 0), SetDataTip(STR_INTRO_NEWGRF_SETTINGS, STR_NULL),
994  NWidget(NWID_SPACER), SetFill(1, 0),
995  EndContainer(),
996  EndContainer(),
998  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_JOIN), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_JOIN_GAME, STR_NULL),
999  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_REFRESH), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_REFRESH, STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP),
1000  EndContainer(),
1001  EndContainer(),
1002  EndContainer(),
1003  EndContainer(),
1004  EndContainer(),
1005  /* BOTTOM */
1009  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_FIND), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_FIND_SERVER, STR_NETWORK_SERVER_LIST_FIND_SERVER_TOOLTIP),
1010  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_ADD), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_ADD_SERVER, STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP),
1011  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_START), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_START_SERVER, STR_NETWORK_SERVER_LIST_START_SERVER_TOOLTIP),
1012  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_CANCEL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
1013  EndContainer(),
1014  NWidget(NWID_SPACER), SetMinimalSize(0, 6), SetResize(1, 0), SetFill(1, 0),
1015  EndContainer(),
1017  NWidget(NWID_SPACER), SetFill(0, 1),
1018  NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE),
1019  EndContainer(),
1020  EndContainer(),
1021  EndContainer(),
1022  EndContainer(),
1023 };
1024 
1025 static WindowDesc _network_game_window_desc(
1026  WDP_CENTER, "list_servers", 1000, 730,
1028  0,
1029  _nested_network_game_widgets, lengthof(_nested_network_game_widgets)
1030 );
1031 
1032 void ShowNetworkGameWindow()
1033 {
1034  static bool first = true;
1037 
1038  /* Only show once */
1039  if (first) {
1040  first = false;
1041  /* Add all servers from the config file to our list. */
1042  for (char **iter = _network_host_list.Begin(); iter != _network_host_list.End(); iter++) {
1043  NetworkAddServer(*iter);
1044  }
1045  }
1046 
1047  new NetworkGameWindow(&_network_game_window_desc);
1048 }
1049 
1051  byte widget_id;
1053 
1054  NetworkStartServerWindow(WindowDesc *desc) : Window(desc), name_editbox(NETWORK_NAME_LENGTH)
1055  {
1056  this->InitNested(WN_NETWORK_WINDOW_START);
1057 
1058  this->querystrings[WID_NSS_GAMENAME] = &this->name_editbox;
1059  this->name_editbox.text.Assign(_settings_client.network.server_name);
1060 
1061  this->SetFocusedWidget(WID_NSS_GAMENAME);
1062  }
1063 
1064  virtual void SetStringParameters(int widget) const
1065  {
1066  switch (widget) {
1067  case WID_NSS_CONNTYPE_BTN:
1069  break;
1070 
1071  case WID_NSS_CLIENTS_TXT:
1073  break;
1074 
1075  case WID_NSS_COMPANIES_TXT:
1077  break;
1078 
1081  break;
1082 
1083  case WID_NSS_LANGUAGE_BTN:
1084  SetDParam(0, STR_NETWORK_LANG_ANY + _settings_client.network.server_lang);
1085  break;
1086  }
1087  }
1088 
1089  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1090  {
1091  switch (widget) {
1092  case WID_NSS_CONNTYPE_BTN:
1094  size->width += padding.width;
1095  size->height += padding.height;
1096  break;
1097  }
1098  }
1099 
1100  virtual void DrawWidget(const Rect &r, int widget) const
1101  {
1102  switch (widget) {
1103  case WID_NSS_SETPWD:
1104  /* If password is set, draw red '*' next to 'Set password' button. */
1105  if (!StrEmpty(_settings_client.network.server_password)) DrawString(r.right + WD_FRAMERECT_LEFT, this->width - WD_FRAMERECT_RIGHT, r.top, "*", TC_RED);
1106  }
1107  }
1108 
1109  virtual void OnClick(Point pt, int widget, int click_count)
1110  {
1111  switch (widget) {
1112  case WID_NSS_CANCEL: // Cancel button
1113  ShowNetworkGameWindow();
1114  break;
1115 
1116  case WID_NSS_SETPWD: // Set password button
1117  this->widget_id = WID_NSS_SETPWD;
1119  ShowQueryString(STR_JUST_RAW_STRING, STR_NETWORK_START_SERVER_SET_PASSWORD, 20, this, CS_ALPHANUMERAL, QSF_NONE);
1120  break;
1121 
1122  case WID_NSS_CONNTYPE_BTN: // Connection type
1123  ShowDropDownMenu(this, _connection_types_dropdown, _settings_client.network.server_advertise, WID_NSS_CONNTYPE_BTN, 0, 0); // do it for widget WID_NSS_CONNTYPE_BTN
1124  break;
1125 
1126  case WID_NSS_CLIENTS_BTND: case WID_NSS_CLIENTS_BTNU: // Click on up/down button for number of clients
1127  case WID_NSS_COMPANIES_BTND: case WID_NSS_COMPANIES_BTNU: // Click on up/down button for number of companies
1128  case WID_NSS_SPECTATORS_BTND: case WID_NSS_SPECTATORS_BTNU: // Click on up/down button for number of spectators
1129  /* Don't allow too fast scrolling. */
1130  if (!(this->flags & WF_TIMEOUT) || this->timeout_timer <= 1) {
1131  this->HandleButtonClick(widget);
1132  this->SetDirty();
1133  switch (widget) {
1134  default: NOT_REACHED();
1137  break;
1140  break;
1143  break;
1144  }
1145  }
1146  _left_button_clicked = false;
1147  break;
1148 
1149  case WID_NSS_CLIENTS_TXT: // Click on number of clients
1150  this->widget_id = WID_NSS_CLIENTS_TXT;
1152  ShowQueryString(STR_JUST_INT, STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS, 4, this, CS_NUMERAL, QSF_NONE);
1153  break;
1154 
1155  case WID_NSS_COMPANIES_TXT: // Click on number of companies
1156  this->widget_id = WID_NSS_COMPANIES_TXT;
1158  ShowQueryString(STR_JUST_INT, STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES, 3, this, CS_NUMERAL, QSF_NONE);
1159  break;
1160 
1161  case WID_NSS_SPECTATORS_TXT: // Click on number of spectators
1162  this->widget_id = WID_NSS_SPECTATORS_TXT;
1164  ShowQueryString(STR_JUST_INT, STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS, 4, this, CS_NUMERAL, QSF_NONE);
1165  break;
1166 
1167  case WID_NSS_LANGUAGE_BTN: { // Language
1168  uint sel = 0;
1169  for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
1170  if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _settings_client.network.server_lang) {
1171  sel = i;
1172  break;
1173  }
1174  }
1175  ShowDropDownMenu(this, _language_dropdown, sel, WID_NSS_LANGUAGE_BTN, 0, 0);
1176  break;
1177  }
1178 
1179  case WID_NSS_GENERATE_GAME: // Start game
1180  _is_network_server = true;
1181  if (_ctrl_pressed) {
1183  } else {
1185  }
1186  break;
1187 
1188  case WID_NSS_LOAD_GAME:
1189  _is_network_server = true;
1191  break;
1192 
1193  case WID_NSS_PLAY_SCENARIO:
1194  _is_network_server = true;
1196  break;
1197 
1199  _is_network_server = true;
1201  break;
1202  }
1203  }
1204 
1205  virtual void OnDropdownSelect(int widget, int index)
1206  {
1207  switch (widget) {
1208  case WID_NSS_CONNTYPE_BTN:
1209  _settings_client.network.server_advertise = (index != 0);
1210  break;
1211  case WID_NSS_LANGUAGE_BTN:
1212  _settings_client.network.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
1213  break;
1214  default:
1215  NOT_REACHED();
1216  }
1217 
1218  this->SetDirty();
1219  }
1220 
1221  virtual void OnEditboxChanged(int wid)
1222  {
1223  if (wid == WID_NSS_GAMENAME) {
1225  }
1226  }
1227 
1228  virtual void OnTimeout()
1229  {
1231  for (const int *widget = raise_widgets; *widget != WIDGET_LIST_END; widget++) {
1232  if (this->IsWidgetLowered(*widget)) {
1233  this->RaiseWidget(*widget);
1234  this->SetWidgetDirty(*widget);
1235  }
1236  }
1237  }
1238 
1239  virtual void OnQueryTextFinished(char *str)
1240  {
1241  if (str == NULL) return;
1242 
1243  if (this->widget_id == WID_NSS_SETPWD) {
1245  } else {
1246  int32 value = atoi(str);
1247  this->SetWidgetDirty(this->widget_id);
1248  switch (this->widget_id) {
1249  default: NOT_REACHED();
1253  }
1254  }
1255 
1256  this->SetDirty();
1257  }
1258 };
1259 
1260 static const NWidgetPart _nested_network_start_server_window_widgets[] = {
1262  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1263  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_NETWORK_START_SERVER_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1264  EndContainer(),
1265  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NSS_BACKGROUND),
1266  NWidget(NWID_VERTICAL), SetPIP(10, 6, 10),
1268  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1269  /* Game name widgets */
1270  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_GAMENAME_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NEW_GAME_NAME, STR_NULL),
1271  NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NSS_GAMENAME), SetMinimalSize(10, 12), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NEW_GAME_NAME_OSKTITLE, STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP),
1272  EndContainer(),
1273  EndContainer(),
1274 
1276  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1277  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_ADVERTISED, STR_NULL),
1278  NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
1279  EndContainer(),
1280  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1281  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_LANGUAGE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN, STR_NULL),
1282  NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_LANGUAGE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP),
1283  EndContainer(),
1284  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1285  NWidget(NWID_SPACER), SetFill(1, 1),
1286  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_SETPWD), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_SET_PASSWORD, STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP),
1287  EndContainer(),
1288  EndContainer(),
1289 
1291  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1292  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_CLIENTS_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS, STR_NULL),
1294  NWidget(WWT_IMGBTN, COLOUR_LIGHT_BLUE, WID_NSS_CLIENTS_BTND), SetMinimalSize(12, 12), SetFill(0, 1), SetDataTip(SPR_ARROW_DOWN, STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP),
1295  NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_NSS_CLIENTS_TXT), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_CLIENTS_SELECT, STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP),
1296  NWidget(WWT_IMGBTN, COLOUR_LIGHT_BLUE, WID_NSS_CLIENTS_BTNU), SetMinimalSize(12, 12), SetFill(0, 1), SetDataTip(SPR_ARROW_UP, STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP),
1297  EndContainer(),
1298  EndContainer(),
1299 
1300  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1301  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_COMPANIES_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES, STR_NULL),
1303  NWidget(WWT_IMGBTN, COLOUR_LIGHT_BLUE, WID_NSS_COMPANIES_BTND), SetMinimalSize(12, 12), SetFill(0, 1), SetDataTip(SPR_ARROW_DOWN, STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP),
1304  NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_NSS_COMPANIES_TXT), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_COMPANIES_SELECT, STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP),
1305  NWidget(WWT_IMGBTN, COLOUR_LIGHT_BLUE, WID_NSS_COMPANIES_BTNU), SetMinimalSize(12, 12), SetFill(0, 1), SetDataTip(SPR_ARROW_UP, STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP),
1306  EndContainer(),
1307  EndContainer(),
1308 
1309  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1310  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_SPECTATORS_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS, STR_NULL),
1312  NWidget(WWT_IMGBTN, COLOUR_LIGHT_BLUE, WID_NSS_SPECTATORS_BTND), SetMinimalSize(12, 12), SetFill(0, 1), SetDataTip(SPR_ARROW_DOWN, STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP),
1313  NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_NSS_SPECTATORS_TXT), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_SPECTATORS_SELECT, STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP),
1314  NWidget(WWT_IMGBTN, COLOUR_LIGHT_BLUE, WID_NSS_SPECTATORS_BTNU), SetMinimalSize(12, 12), SetFill(0, 1), SetDataTip(SPR_ARROW_UP, STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP),
1315  EndContainer(),
1316  EndContainer(),
1317  EndContainer(),
1318 
1319  /* 'generate game' and 'load game' buttons */
1321  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_GENERATE_GAME), SetDataTip(STR_INTRO_NEW_GAME, STR_INTRO_TOOLTIP_NEW_GAME), SetFill(1, 0),
1322  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_LOAD_GAME), SetDataTip(STR_INTRO_LOAD_GAME, STR_INTRO_TOOLTIP_LOAD_GAME), SetFill(1, 0),
1323  EndContainer(),
1324 
1325  /* 'play scenario' and 'play heightmap' buttons */
1327  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_PLAY_SCENARIO), SetDataTip(STR_INTRO_PLAY_SCENARIO, STR_INTRO_TOOLTIP_PLAY_SCENARIO), SetFill(1, 0),
1328  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_PLAY_HEIGHTMAP), SetDataTip(STR_INTRO_PLAY_HEIGHTMAP, STR_INTRO_TOOLTIP_PLAY_HEIGHTMAP), SetFill(1, 0),
1329  EndContainer(),
1330 
1332  NWidget(NWID_SPACER), SetFill(1, 0),
1333  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_CANCEL), SetDataTip(STR_BUTTON_CANCEL, STR_NULL), SetMinimalSize(128, 12),
1334  NWidget(NWID_SPACER), SetFill(1, 0),
1335  EndContainer(),
1336  EndContainer(),
1337  EndContainer(),
1338 };
1339 
1340 static WindowDesc _network_start_server_window_desc(
1341  WDP_CENTER, NULL, 0, 0,
1343  0,
1344  _nested_network_start_server_window_widgets, lengthof(_nested_network_start_server_window_widgets)
1345 );
1346 
1347 static void ShowNetworkStartServerWindow()
1348 {
1351 
1352  new NetworkStartServerWindow(&_network_start_server_window_desc);
1353 }
1354 
1355 struct NetworkLobbyWindow : public Window {
1358  NetworkCompanyInfo company_info[MAX_COMPANIES];
1359  Scrollbar *vscroll;
1360 
1362  Window(desc), company(INVALID_COMPANY), server(ngl)
1363  {
1364  this->CreateNestedTree();
1365  this->vscroll = this->GetScrollbar(WID_NL_SCROLLBAR);
1366  this->FinishInitNested(WN_NETWORK_WINDOW_LOBBY);
1367  }
1368 
1369  CompanyID NetworkLobbyFindCompanyIndex(byte pos) const
1370  {
1371  /* Scroll through all this->company_info and get the 'pos' item that is not empty. */
1372  for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
1373  if (!StrEmpty(this->company_info[i].company_name)) {
1374  if (pos-- == 0) return i;
1375  }
1376  }
1377 
1378  return COMPANY_FIRST;
1379  }
1380 
1381  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1382  {
1383  switch (widget) {
1384  case WID_NL_HEADER:
1386  break;
1387 
1388  case WID_NL_MATRIX:
1389  resize->height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
1390  size->height = 10 * resize->height;
1391  break;
1392 
1393  case WID_NL_DETAILS:
1394  size->height = 30 + 11 * FONT_HEIGHT_NORMAL;
1395  break;
1396  }
1397  }
1398 
1399  virtual void SetStringParameters(int widget) const
1400  {
1401  switch (widget) {
1402  case WID_NL_TEXT:
1403  SetDParamStr(0, this->server->info.server_name);
1404  break;
1405  }
1406  }
1407 
1408  virtual void DrawWidget(const Rect &r, int widget) const
1409  {
1410  switch (widget) {
1411  case WID_NL_DETAILS:
1412  this->DrawDetails(r);
1413  break;
1414 
1415  case WID_NL_MATRIX:
1416  this->DrawMatrix(r);
1417  break;
1418  }
1419  }
1420 
1421  virtual void OnPaint()
1422  {
1423  const NetworkGameInfo *gi = &this->server->info;
1424 
1425  /* Join button is disabled when no company is selected and for AI companies. */
1426  this->SetWidgetDisabledState(WID_NL_JOIN, this->company == INVALID_COMPANY || GetLobbyCompanyInfo(this->company)->ai);
1427  /* Cannot start new company if there are too many. */
1428  this->SetWidgetDisabledState(WID_NL_NEW, gi->companies_on >= gi->companies_max);
1429  /* Cannot spectate if there are too many spectators. */
1430  this->SetWidgetDisabledState(WID_NL_SPECTATE, gi->spectators_on >= gi->spectators_max);
1431 
1432  this->vscroll->SetCount(gi->companies_on);
1433 
1434  /* Draw window widgets */
1435  this->DrawWidgets();
1436  }
1437 
1438  void DrawMatrix(const Rect &r) const
1439  {
1440  bool rtl = _current_text_dir == TD_RTL;
1441  uint left = r.left + WD_FRAMERECT_LEFT;
1442  uint right = r.right - WD_FRAMERECT_RIGHT;
1443 
1444  Dimension lock_size = GetSpriteSize(SPR_LOCK);
1445  int lock_width = lock_size.width;
1446  int lock_y_offset = (this->resize.step_height - WD_MATRIX_TOP - WD_MATRIX_BOTTOM - lock_size.height) / 2;
1447 
1448  Dimension profit_size = GetSpriteSize(SPR_PROFIT_LOT);
1449  int profit_width = lock_size.width;
1450  int profit_y_offset = (this->resize.step_height - WD_MATRIX_TOP - WD_MATRIX_BOTTOM - profit_size.height) / 2;
1451 
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;
1456 
1457  int y = r.top + WD_MATRIX_TOP;
1458  /* Draw company list */
1459  int pos = this->vscroll->GetPosition();
1460  while (pos < this->server->info.companies_on) {
1461  byte company = NetworkLobbyFindCompanyIndex(pos);
1462  bool income = false;
1463  if (this->company == company) {
1464  GfxFillRect(r.left + 1, y - 2, r.right - 1, y + FONT_HEIGHT_NORMAL, PC_GREY); // show highlighted item with a different colour
1465  }
1466 
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);
1469 
1470  /* If the company's income was positive puts a green dot else a red dot */
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);
1473 
1474  pos++;
1475  y += this->resize.step_height;
1476  if (pos >= this->vscroll->GetPosition() + this->vscroll->GetCapacity()) break;
1477  }
1478  }
1479 
1480  void DrawDetails(const Rect &r) const
1481  {
1482  const int detail_height = 12 + FONT_HEIGHT_NORMAL + 12;
1483  /* Draw info about selected company when it is selected in the left window. */
1484  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + detail_height - 1, PC_DARK_BLUE);
1485  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + 12, STR_NETWORK_GAME_LOBBY_COMPANY_INFO, TC_FROMSTRING, SA_HOR_CENTER);
1486 
1487  if (this->company == INVALID_COMPANY || StrEmpty(this->company_info[this->company].company_name)) return;
1488 
1489  int y = r.top + detail_height + 4;
1490  const NetworkGameInfo *gi = &this->server->info;
1491 
1492  SetDParam(0, gi->clients_on);
1493  SetDParam(1, gi->clients_max);
1494  SetDParam(2, gi->companies_on);
1495  SetDParam(3, gi->companies_max);
1496  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CLIENTS);
1497  y += FONT_HEIGHT_NORMAL;
1498 
1499  SetDParamStr(0, this->company_info[this->company].company_name);
1500  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_COMPANY_NAME);
1501  y += FONT_HEIGHT_NORMAL;
1502 
1503  SetDParam(0, this->company_info[this->company].inaugurated_year);
1504  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR); // inauguration year
1505  y += FONT_HEIGHT_NORMAL;
1506 
1507  SetDParam(0, this->company_info[this->company].company_value);
1508  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_VALUE); // company value
1509  y += FONT_HEIGHT_NORMAL;
1510 
1511  SetDParam(0, this->company_info[this->company].money);
1512  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_CURRENT_BALANCE); // current balance
1513  y += FONT_HEIGHT_NORMAL;
1514 
1515  SetDParam(0, this->company_info[this->company].income);
1516  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_LAST_YEARS_INCOME); // last year's income
1517  y += FONT_HEIGHT_NORMAL;
1518 
1519  SetDParam(0, this->company_info[this->company].performance);
1520  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_PERFORMANCE); // performance
1521  y += FONT_HEIGHT_NORMAL;
1522 
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]);
1528  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_VEHICLES); // vehicles
1529  y += FONT_HEIGHT_NORMAL;
1530 
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]);
1536  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_STATIONS); // stations
1537  y += FONT_HEIGHT_NORMAL;
1538 
1539  SetDParamStr(0, this->company_info[this->company].clients);
1540  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_PLAYERS); // players
1541  }
1542 
1543  virtual void OnClick(Point pt, int widget, int click_count)
1544  {
1545  switch (widget) {
1546  case WID_NL_CANCEL: // Cancel button
1547  ShowNetworkGameWindow();
1548  break;
1549 
1550  case WID_NL_MATRIX: { // Company list
1551  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NL_MATRIX);
1552  this->company = (id_v >= this->server->info.companies_on) ? INVALID_COMPANY : NetworkLobbyFindCompanyIndex(id_v);
1553  this->SetDirty();
1554 
1555  /* FIXME the disabling should go into some InvalidateData, which is called instead of the SetDirty */
1556  if (click_count > 1 && !this->IsWidgetDisabled(WID_NL_JOIN)) this->OnClick(pt, WID_NL_JOIN, 1);
1557  break;
1558  }
1559 
1560  case WID_NL_JOIN: // Join company
1561  /* Button can be clicked only when it is enabled. */
1562  NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), this->company);
1563  break;
1564 
1565  case WID_NL_NEW: // New company
1567  break;
1568 
1569  case WID_NL_SPECTATE: // Spectate game
1571  break;
1572 
1573  case WID_NL_REFRESH: // Refresh
1574  NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
1576  /* Clear the information so removed companies don't remain */
1577  memset(this->company_info, 0, sizeof(this->company_info));
1578  break;
1579  }
1580  }
1581 
1582  virtual void OnResize()
1583  {
1584  this->vscroll->SetCapacityFromWidget(this, WID_NL_MATRIX);
1585  }
1586 };
1587 
1588 static const NWidgetPart _nested_network_lobby_window_widgets[] = {
1590  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1591  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_NETWORK_GAME_LOBBY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1592  EndContainer(),
1593  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NL_BACKGROUND),
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),
1596  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 10),
1597  /* Company list. */
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),
1601  EndContainer(),
1602  NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NL_SCROLLBAR),
1604  /* Company info. */
1605  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NL_DETAILS), SetMinimalSize(232, 0), SetResize(1, 1), SetFill(1, 1), EndContainer(),
1606  EndContainer(),
1608  /* Buttons. */
1611  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_JOIN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_GAME_LOBBY_JOIN_COMPANY, STR_NETWORK_GAME_LOBBY_JOIN_COMPANY_TOOLTIP),
1612  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_NEW), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_GAME_LOBBY_NEW_COMPANY, STR_NETWORK_GAME_LOBBY_NEW_COMPANY_TOOLTIP),
1613  EndContainer(),
1615  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_SPECTATE), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_GAME_LOBBY_SPECTATE_GAME, STR_NETWORK_GAME_LOBBY_SPECTATE_GAME_TOOLTIP),
1616  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_REFRESH), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_REFRESH, STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP),
1617  EndContainer(),
1619  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_CANCEL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
1620  NWidget(NWID_SPACER), SetFill(1, 1),
1621  EndContainer(),
1622  EndContainer(),
1624  EndContainer(),
1625 };
1626 
1627 static WindowDesc _network_lobby_window_desc(
1628  WDP_CENTER, NULL, 0, 0,
1630  0,
1631  _nested_network_lobby_window_widgets, lengthof(_nested_network_lobby_window_widgets)
1632 );
1633 
1639 {
1642 
1643  NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
1645 
1646  new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
1647 }
1648 
1655 {
1657  return (lobby != NULL && company < MAX_COMPANIES) ? &lobby->company_info[company] : NULL;
1658 }
1659 
1660 /* The window below gives information about the connected clients
1661  * and also makes able to give money to them, kick them (if server)
1662  * and stuff like that. */
1663 
1664 extern void DrawCompanyIcon(CompanyID cid, int x, int y);
1665 
1671 
1672 static const NWidgetPart _nested_client_list_popup_widgets[] = {
1673  NWidget(WWT_PANEL, COLOUR_GREY, WID_CLP_PANEL), EndContainer(),
1674 };
1675 
1676 static WindowDesc _client_list_popup_desc(
1677  WDP_AUTO, NULL, 0, 0,
1679  0,
1680  _nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets)
1681 );
1682 
1683 /* Here we start to define the options out of the menu */
1684 static void ClientList_Kick(const NetworkClientInfo *ci)
1685 {
1687 }
1688 
1689 static void ClientList_Ban(const NetworkClientInfo *ci)
1690 {
1692 }
1693 
1694 static void ClientList_GiveMoney(const NetworkClientInfo *ci)
1695 {
1696  ShowNetworkGiveMoneyWindow(ci->client_playas);
1697 }
1698 
1699 static void ClientList_SpeakToClient(const NetworkClientInfo *ci)
1700 {
1702 }
1703 
1704 static void ClientList_SpeakToCompany(const NetworkClientInfo *ci)
1705 {
1707 }
1708 
1709 static void ClientList_SpeakToAll(const NetworkClientInfo *ci)
1710 {
1712 }
1713 
1720  };
1721 
1722  uint sel_index;
1723  ClientID client_id;
1724  Point desired_location;
1726 
1732  inline void AddAction(StringID name, ClientList_Action_Proc *proc)
1733  {
1734  ClientListAction *action = this->actions.Append();
1735  action->name = name;
1736  action->proc = proc;
1737  }
1738 
1739  NetworkClientListPopupWindow(WindowDesc *desc, int x, int y, ClientID client_id) :
1740  Window(desc),
1741  sel_index(0), client_id(client_id)
1742  {
1743  this->desired_location.x = x;
1744  this->desired_location.y = y;
1745 
1746  const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
1747 
1748  if (_network_own_client_id != ci->client_id) {
1749  this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, &ClientList_SpeakToClient);
1750  }
1751 
1753  this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, &ClientList_SpeakToCompany);
1754  }
1755  this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, &ClientList_SpeakToAll);
1756 
1757  if (_network_own_client_id != ci->client_id) {
1758  /* We are no spectator and the company we want to give money to is no spectator and money gifts are allowed. */
1760  this->AddAction(STR_NETWORK_CLIENTLIST_GIVE_MONEY, &ClientList_GiveMoney);
1761  }
1762  }
1763 
1764  /* A server can kick clients (but not himself). */
1766  this->AddAction(STR_NETWORK_CLIENTLIST_KICK, &ClientList_Kick);
1767  this->AddAction(STR_NETWORK_CLIENTLIST_BAN, &ClientList_Ban);
1768  }
1769 
1770  this->InitNested(client_id);
1771  CLRBITS(this->flags, WF_WHITE_BORDER);
1772  }
1773 
1774  virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
1775  {
1776  return this->desired_location;
1777  }
1778 
1779  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1780  {
1781  Dimension d = *size;
1782  for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++) {
1783  d = maxdim(GetStringBoundingBox(action->name), d);
1784  }
1785 
1786  d.height *= this->actions.Length();
1788  d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1789  *size = d;
1790  }
1791 
1792  virtual void DrawWidget(const Rect &r, int widget) const
1793  {
1794  /* Draw the actions */
1795  int sel = this->sel_index;
1796  int y = r.top + WD_FRAMERECT_TOP;
1797  for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++, y += FONT_HEIGHT_NORMAL) {
1798  TextColour colour;
1799  if (sel-- == 0) { // Selected item, highlight it
1800  GfxFillRect(r.left + 1, y, r.right - 1, y + FONT_HEIGHT_NORMAL - 1, PC_BLACK);
1801  colour = TC_WHITE;
1802  } else {
1803  colour = TC_BLACK;
1804  }
1805 
1806  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, action->name, colour);
1807  }
1808  }
1809 
1810  virtual void OnMouseLoop()
1811  {
1812  /* We selected an action */
1813  uint index = (_cursor.pos.y - this->top - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL;
1814 
1815  if (_left_button_down) {
1816  if (index == this->sel_index || index >= this->actions.Length()) return;
1817 
1818  this->sel_index = index;
1819  this->SetDirty();
1820  } else {
1821  if (index < this->actions.Length() && _cursor.pos.y >= this->top) {
1822  const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(this->client_id);
1823  if (ci != NULL) this->actions[index].proc(ci);
1824  }
1825 
1827  }
1828  }
1829 };
1830 
1834 static void PopupClientList(ClientID client_id, int x, int y)
1835 {
1837 
1838  if (NetworkClientInfo::GetByClientID(client_id) == NULL) return;
1839 
1840  new NetworkClientListPopupWindow(&_client_list_popup_desc, x, y, client_id);
1841 }
1842 
1843 static const NWidgetPart _nested_client_list_widgets[] = {
1845  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1846  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1847  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1848  EndContainer(),
1850 };
1851 
1852 static WindowDesc _client_list_desc(
1853  WDP_AUTO, "list_clients", 0, 0,
1855  0,
1856  _nested_client_list_widgets, lengthof(_nested_client_list_widgets)
1857 );
1858 
1863  int selected_item;
1864 
1865  uint server_client_width;
1866  uint line_height;
1867 
1868  Dimension icon_size;
1869 
1870  NetworkClientListWindow(WindowDesc *desc, WindowNumber window_number) :
1871  Window(desc),
1872  selected_item(-1)
1873  {
1874  this->InitNested(window_number);
1875  }
1876 
1881  {
1882  int num = 0;
1883  const NetworkClientInfo *ci;
1884 
1885  /* Should be replaced with a loop through all clients */
1886  FOR_ALL_CLIENT_INFOS(ci) {
1887  if (ci->client_playas != COMPANY_INACTIVE_CLIENT) num++;
1888  }
1889 
1890  num *= this->line_height;
1891 
1892  int diff = (num + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM) - (this->GetWidget<NWidgetBase>(WID_CL_PANEL)->current_y);
1893  /* If height is changed */
1894  if (diff != 0) {
1895  ResizeWindow(this, 0, diff, false);
1896  return false;
1897  }
1898  return true;
1899  }
1900 
1901  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1902  {
1903  if (widget != WID_CL_PANEL) return;
1904 
1905  this->server_client_width = max(GetStringBoundingBox(STR_NETWORK_SERVER).width, GetStringBoundingBox(STR_NETWORK_CLIENT).width) + WD_FRAMERECT_RIGHT;
1906  this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
1907  this->line_height = max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
1908 
1909  uint width = 100; // Default width
1910  const NetworkClientInfo *ci;
1911  FOR_ALL_CLIENT_INFOS(ci) {
1912  width = max(width, GetStringBoundingBox(ci->client_name).width);
1913  }
1914 
1915  size->width = WD_FRAMERECT_LEFT + this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT + width + WD_FRAMERECT_RIGHT;
1916  }
1917 
1918  virtual void OnPaint()
1919  {
1920  /* Check if we need to reset the height */
1921  if (!this->CheckClientListHeight()) return;
1922 
1923  this->DrawWidgets();
1924  }
1925 
1926  virtual void DrawWidget(const Rect &r, int widget) const
1927  {
1928  if (widget != WID_CL_PANEL) return;
1929 
1930  bool rtl = _current_text_dir == TD_RTL;
1931  int icon_offset = (this->line_height - icon_size.height) / 2;
1932  int text_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
1933 
1934  uint y = r.top + WD_FRAMERECT_TOP;
1935  uint left = r.left + WD_FRAMERECT_LEFT;
1936  uint right = r.right - WD_FRAMERECT_RIGHT;
1937  uint type_icon_width = this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT;
1938 
1939 
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;
1945 
1946  int i = 0;
1947  const NetworkClientInfo *ci;
1948  FOR_ALL_CLIENT_INFOS(ci) {
1949  TextColour colour;
1950  if (this->selected_item == i++) { // Selected item, highlight it
1951  GfxFillRect(r.left + 1, y, r.right - 1, y + this->line_height - 1, PC_BLACK);
1952  colour = TC_WHITE;
1953  } else {
1954  colour = TC_BLACK;
1955  }
1956 
1957  if (ci->client_id == CLIENT_ID_SERVER) {
1958  DrawString(type_left, type_right, y + text_offset, STR_NETWORK_SERVER, colour);
1959  } else {
1960  DrawString(type_left, type_right, y + text_offset, STR_NETWORK_CLIENT, colour);
1961  }
1962 
1963  /* Filter out spectators */
1964  if (Company::IsValidID(ci->client_playas)) DrawCompanyIcon(ci->client_playas, icon_left, y + icon_offset);
1965 
1966  DrawString(name_left, name_right, y + text_offset, ci->client_name, colour);
1967 
1968  y += line_height;
1969  }
1970  }
1971 
1972  virtual void OnClick(Point pt, int widget, int click_count)
1973  {
1974  /* Show the popup with option */
1975  if (this->selected_item != -1) {
1976  NetworkClientInfo *ci;
1977 
1978  int client_no = this->selected_item;
1979  FOR_ALL_CLIENT_INFOS(ci) {
1980  if (client_no == 0) break;
1981  client_no--;
1982  }
1983 
1984  if (ci != NULL) PopupClientList(ci->client_id, pt.x + this->left, pt.y + this->top);
1985  }
1986  }
1987 
1988  virtual void OnMouseOver(Point pt, int widget)
1989  {
1990  /* -1 means we left the current window */
1991  if (pt.y == -1) {
1992  this->selected_item = -1;
1993  this->SetDirty();
1994  return;
1995  }
1996 
1997  /* Find the new selected item (if any) */
1998  pt.y -= this->GetWidget<NWidgetBase>(WID_CL_PANEL)->pos_y;
1999  int item = -1;
2001  item = (pt.y - WD_FRAMERECT_TOP) / this->line_height;
2002  }
2003 
2004  /* It did not change.. no update! */
2005  if (item == this->selected_item) return;
2006  this->selected_item = item;
2007 
2008  /* Repaint */
2009  this->SetDirty();
2010  }
2011 };
2012 
2013 void ShowClientList()
2014 {
2015  AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0);
2016 }
2017 
2022 
2024  NetworkPasswordType password_type;
2025 
2027  {
2029  this->InitNested(WN_NETWORK_STATUS_WINDOW_JOIN);
2030  }
2031 
2032  virtual void DrawWidget(const Rect &r, int widget) const
2033  {
2034  if (widget != WID_NJS_BACKGROUND) return;
2035 
2036  uint8 progress; // used for progress bar
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:
2041  progress = 10; // first two stages 10%
2042  break;
2043  case NETWORK_JOIN_STATUS_WAITING:
2044  SetDParam(0, _network_join_waiting);
2045  DrawString(r.left + 2, r.right - 2, r.top + 20 + FONT_HEIGHT_NORMAL, STR_NETWORK_CONNECTING_WAITING, TC_FROMSTRING, SA_HOR_CENTER);
2046  progress = 15; // third stage is 15%
2047  break;
2048  case NETWORK_JOIN_STATUS_DOWNLOADING:
2049  SetDParam(0, _network_join_bytes);
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) {
2053  progress = 15; // We don't have the final size yet; the server is still compressing!
2054  break;
2055  }
2056  FALLTHROUGH;
2057 
2058  default: // Waiting is 15%, so the resting receivement of map is maximum 70%
2059  progress = 15 + _network_join_bytes * (100 - 15) / _network_join_bytes_total;
2060  }
2061 
2062  /* Draw nice progress bar :) */
2063  DrawFrameRect(r.left + 20, r.top + 5, (int)((this->width - 20) * progress / 100), r.top + 15, COLOUR_MAUVE, FR_NONE);
2064  }
2065 
2066  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2067  {
2068  if (widget != WID_NJS_BACKGROUND) return;
2069 
2070  size->height = 25 + 2 * FONT_HEIGHT_NORMAL;
2071 
2072  /* Account for the statuses */
2073  uint width = 0;
2074  for (uint i = 0; i < NETWORK_JOIN_STATUS_END; i++) {
2075  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_1 + i).width);
2076  }
2077 
2078  /* For the number of waiting (other) players */
2080  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_WAITING).width);
2081 
2082  /* Account for downloading ~ 10 MiB */
2083  SetDParamMaxDigits(0, 8);
2084  SetDParamMaxDigits(1, 8);
2085  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_DOWNLOADING_1).width);
2086  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_DOWNLOADING_2).width);
2087 
2088  /* Give a bit more clearing for the widest strings than strictly needed */
2089  size->width = width + WD_FRAMERECT_LEFT + WD_FRAMERECT_BOTTOM + 10;
2090  }
2091 
2092  virtual void OnClick(Point pt, int widget, int click_count)
2093  {
2094  if (widget == WID_NJS_CANCELOK) { // Disconnect button
2096  SwitchToMode(SM_MENU);
2097  ShowNetworkGameWindow();
2098  }
2099  }
2100 
2101  virtual void OnQueryTextFinished(char *str)
2102  {
2103  if (StrEmpty(str)) {
2105  ShowNetworkGameWindow();
2106  return;
2107  }
2108 
2109  switch (this->password_type) {
2112  default: NOT_REACHED();
2113  }
2114  }
2115 };
2116 
2117 static const NWidgetPart _nested_network_join_status_window_widgets[] = {
2118  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_CONNECTING_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2119  NWidget(WWT_PANEL, COLOUR_GREY),
2120  NWidget(WWT_EMPTY, COLOUR_GREY, WID_NJS_BACKGROUND),
2122  NWidget(NWID_SPACER), SetMinimalSize(75, 0), SetFill(1, 0),
2123  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NJS_CANCELOK), SetMinimalSize(101, 12), SetDataTip(STR_NETWORK_CONNECTION_DISCONNECT, STR_NULL),
2124  NWidget(NWID_SPACER), SetMinimalSize(75, 0), SetFill(1, 0),
2125  EndContainer(),
2127  EndContainer(),
2128 };
2129 
2130 static WindowDesc _network_join_status_window_desc(
2131  WDP_CENTER, NULL, 0, 0,
2133  WDF_MODAL,
2134  _nested_network_join_status_window_widgets, lengthof(_nested_network_join_status_window_widgets)
2135 );
2136 
2137 void ShowJoinStatusWindow()
2138 {
2140  new NetworkJoinStatusWindow(&_network_join_status_window_desc);
2141 }
2142 
2143 void ShowNetworkNeedPassword(NetworkPasswordType npt)
2144 {
2146  if (w == NULL) return;
2147  w->password_type = npt;
2148 
2149  StringID caption;
2150  switch (npt) {
2151  default: NOT_REACHED();
2152  case NETWORK_GAME_PASSWORD: caption = STR_NETWORK_NEED_GAME_PASSWORD_CAPTION; break;
2153  case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break;
2154  }
2155  ShowQueryString(STR_EMPTY, caption, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_NONE);
2156 }
2157 
2160 
2161  NetworkCompanyPasswordWindow(WindowDesc *desc, Window *parent) : Window(desc), password_editbox(lengthof(_settings_client.network.default_company_pass))
2162  {
2163  this->InitNested(0);
2164 
2165  this->parent = parent;
2166  this->querystrings[WID_NCP_PASSWORD] = &this->password_editbox;
2167  this->password_editbox.cancel_button = WID_NCP_CANCEL;
2168  this->password_editbox.ok_button = WID_NCP_OK;
2169  this->SetFocusedWidget(WID_NCP_PASSWORD);
2170  }
2171 
2172  void OnOk()
2173  {
2174  if (this->IsWidgetLowered(WID_NCP_SAVE_AS_DEFAULT_PASSWORD)) {
2176  }
2177 
2178  NetworkChangeCompanyPassword(_local_company, this->password_editbox.text.buf);
2179  }
2180 
2181  virtual void OnClick(Point pt, int widget, int click_count)
2182  {
2183  switch (widget) {
2184  case WID_NCP_OK:
2185  this->OnOk();
2186  FALLTHROUGH;
2187 
2188  case WID_NCP_CANCEL:
2189  delete this;
2190  break;
2191 
2193  this->ToggleWidgetLoweredState(WID_NCP_SAVE_AS_DEFAULT_PASSWORD);
2194  this->SetDirty();
2195  break;
2196  }
2197  }
2198 };
2199 
2200 static const NWidgetPart _nested_network_company_password_window_widgets[] = {
2202  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2203  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_COMPANY_PASSWORD_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2204  EndContainer(),
2205  NWidget(WWT_PANEL, COLOUR_GREY, WID_NCP_BACKGROUND),
2206  NWidget(NWID_VERTICAL), SetPIP(5, 5, 5),
2207  NWidget(NWID_HORIZONTAL), SetPIP(5, 5, 5),
2208  NWidget(WWT_TEXT, COLOUR_GREY, WID_NCP_LABEL), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_NULL),
2209  NWidget(WWT_EDITBOX, COLOUR_GREY, WID_NCP_PASSWORD), SetFill(1, 0), SetMinimalSize(194, 12), SetDataTip(STR_COMPANY_VIEW_SET_PASSWORD, STR_NULL),
2210  EndContainer(),
2211  NWidget(NWID_HORIZONTAL), SetPIP(5, 0, 5),
2212  NWidget(NWID_SPACER), SetFill(1, 0),
2214  SetDataTip(STR_COMPANY_PASSWORD_MAKE_DEFAULT, STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP),
2215  EndContainer(),
2216  EndContainer(),
2217  EndContainer(),
2219  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NCP_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_COMPANY_PASSWORD_CANCEL),
2220  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NCP_OK), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_COMPANY_PASSWORD_OK),
2221  EndContainer(),
2222 };
2223 
2224 static WindowDesc _network_company_password_window_desc(
2225  WDP_AUTO, NULL, 0, 0,
2227  0,
2228  _nested_network_company_password_window_widgets, lengthof(_nested_network_company_password_window_widgets)
2229 );
2230 
2231 void ShowNetworkCompanyPasswordWindow(Window *parent)
2232 {
2234 
2235  new NetworkCompanyPasswordWindow(&_network_company_password_window_desc, parent);
2236 }
2237 
2238 #endif /* ENABLE_NETWORK */
EventState
State of handling an event.
Definition: window_type.h:701
Date start_date
When the game started.
Definition: game.h:38
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
static const uint NETWORK_CLIENT_NAME_LENGTH
The maximum length of a client&#39;s name, in bytes including &#39;\0&#39;.
Definition: config.h:49
byte spectators_max
Max spectators allowed on server.
Definition: game.h:55
Label for &#39;connection type&#39;.
uint16 map_height
Map height.
Definition: game.h:41
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:48
Panel of the window.
Send message/notice to all clients (All)
Definition: network_type.h:83
Main handle for clientlist.
SizingType
Different forms of sizing nested widgets, using NWidgetBase::AssignSizePosition() ...
Definition: widget_type.h:111
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
Ban, or kick, everyone joined from the given client&#39;s IP.
Network game window.
Definition: window_type.h:29
void RebuildDone()
Notify the sortlist that the rebuild is done.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
bool CheckClientListHeight()
Finds the amount of clients and set the height correct.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
Main panel.
Spacer for game actual details.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Container for all information known about a client.
Definition: network_base.h:27
virtual void OnEditboxChanged(int wid)
The text in an editbox has been edited.
Horizontally center the text.
Definition: gfx_func.h:99
void ScrollTowards(int position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
Definition: widget_type.h:731
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:112
bool server_advertise
advertise the server to the masterserver
Point pos
logical mouse position
Definition: gfx_type.h:119
static NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
Definition: widget_type.h:1146
uint resize_x
Horizontal resize step (0 means not resizable).
Definition: widget_type.h:166
uint8 lan_internet
search on the LAN or internet for servers
uint16 last_port
port of the last joined server
High level window description.
Definition: window_gui.h:168
&#39;Max spectators&#39; text.
Client list; Window numbers:
Definition: window_type.h:474
void SetMinimalSize(uint min_x, uint min_y)
Set minimal size of the widget.
Definition: widget.cpp:817
&#39;Cancel&#39; button.
EconomySettings economy
settings to change the economy
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
The client is joining.
Definition: company_type.h:35
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
char server_name[NETWORK_NAME_LENGTH]
name of the server
Load game button.
NWidgetCore * GetWidgetFromPos(int x, int y)
Retrieve a widget by its position.
Baseclass for container widgets.
Definition: widget_type.h:368
static NetworkRecvStatus SendGamePassword(const char *password)
Set the game password as requested.
Switch to game intro menu.
Definition: openttd.h:32
static bool IsInsideMM(const T x, const uint min, const uint max)
Checks if a value is in an interval.
Definition: math_func.hpp:266
void StartNewGameWithoutGUI(uint seed)
Start a normal game without the GUI.
NetworkGameList * next
Next pointer to make a linked game list.
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
GUIs related to networking.
Scrollbar data structure.
Definition: widget_type.h:589
Label for &#39;max spectators&#39;.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:398
byte server_lang
Language of the server (we should make a nice table for this)
Definition: game.h:50
static void DrawMatrix(const Rect &r, Colours colour, bool clicked, uint16 data, uint resize_x, uint resize_y)
Draw a matrix widget.
Definition: widget.cpp:278
static int CDECL NGameNameSorter(NetworkGameList *const *a, NetworkGameList *const *b)
Sort servers by name.
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
Normal amount of vertical space between two paragraphs of text.
Definition: window_gui.h:139
Horizontal container.
Definition: widget_type.h:75
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1105
void ResetState()
Reset the matching state to process a new item.
The passed event is not handled.
Definition: window_type.h:703
Background of the window.
void SetSortFuncs(SortFunction *const *n_funcs)
Hand the array of sort function pointers to the sort list.
bool GetState() const
Get the matching state of the current item.
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1065
virtual void OnEditboxChanged(int wid)
The text in an editbox has been edited.
NWidgetBase * tail
Pointer to last widget in container.
Definition: widget_type.h:383
Input field for the password.
virtual void OnPaint()
The window must be repainted.
Label for &#39;language spoken&#39;.
ClientID client_id
Client identifier (same as ClientState->client_id)
Definition: network_base.h:28
Popup for the client list; Window numbers:
Definition: window_type.h:480
bool version_compatible
Can we connect to this server or not? (based on server_revision)
Definition: game.h:46
&#39;Cancel&#39; button.
NetworkJoinStatus _network_join_status
The status of joining.
a textbox for typing
Definition: widget_type.h:71
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
static const int ACTION_CLEAR
Clear editbox.
NetworkGameList * last_joined
the last joined server
static const uint MAX_CLIENTS
How many clients can we have.
Definition: network_type.h:20
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Sending and receiving UDP messages.
&#39;New company&#39; button.
static bool IsInsideBS(const T x, const uint base, const uint size)
Checks if a value is between a window started at some base point.
Definition: math_func.hpp:250
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
Client part of the network protocol.
void Clear()
Remove all items from the list.
QueryString filter_editbox
Editbox for filter on servers.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
void NetworkGameListRemoveItem(NetworkGameList *remove)
Remove an item from the gamelist linked list.
void Compact()
Compact the list down to the smallest block size boundary.
ServerListPosition list_pos
position of the selected server
Wrapper for (un)resolved network addresses; there&#39;s no reason to transform a numeric IP to a string a...
Definition: address.h:31
const T * Begin() const
Get the pointer to the first item (const)
static const uint GENERATE_NEW_SEED
Create a new random seed.
Definition: genworld.h:25
bool give_money
allow giving other companies money
Toggle &#39;button&#39; for saving the current password as default password.
Close box (at top-left of a window)
Definition: widget_type.h:69
QueryString password_editbox
Password editbox.
Offset at top of a matrix cell.
Definition: window_gui.h:80
Header container of the matrix.
uint16 map_width
Map width.
Definition: game.h:40
Send message/notice to only a certain client (Private)
Definition: network_type.h:85
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0...
Heading text.
Panel with editbox to set client name.
static int CDECL NGameMapSizeSorter(NetworkGameList *const *a, NetworkGameList *const *b)
Sort servers by map size.
String filter and state.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
The client is spectating.
Definition: company_type.h:37
The client wants a new company.
Definition: company_type.h:36
bool IsWidgetVisible(NetworkGameWidgets widget) const
Checks whether the given widget is actually visible.
Simple vector template class.
return success even when the text didn&#39;t change
Definition: textbuf_gui.h:22
Play scenario button.
Base core network types and some helper functions to access them.
void SetFilterFuncs(FilterFunction *const *n_funcs)
Hand the array of filter function pointers to the sort list.
Structure with information shown in the game list (GUI)
#define CLRBITS(x, y)
Clears several bits in a variable.
&#39;Max clients&#39; uparrow.
virtual void OnMouseOver(Point pt, int widget)
The mouse is currently moving over the window or has just moved outside of the window.
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
virtual void OnPaint()
The window must be repainted.
uint smallest_x
Smallest horizontal size of the widget in a filled window.
Definition: widget_type.h:171
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
&#39;Add server&#39; button.
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
&#39;Years&#39; button.
Label "Last joined server:".
const T * End() const
Get the pointer behind the last valid item (const)
&#39;Language spoken&#39; droplist button.
void SetListing(Listing l)
Import sort conditions.
Pure simple text.
Definition: widget_type.h:58
char server_name[NETWORK_NAME_LENGTH]
Server name.
Definition: game.h:42
bool NeedRebuild() const
Check if a rebuild is needed.
Servers always have this ID.
Definition: network_type.h:45
virtual EventState OnKeyPress(WChar key, uint16 keycode)
A key has been pressed.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
void SortNetworkGameList()
Sort the server list.
void UpdateNetworkGameWindow()
Update the network new window because a new server is found on the network.
Definition: network_gui.cpp:84
static const uint MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER
Minimum width before adding a new header.
Definition: network_gui.cpp:95
bool _left_button_clicked
Is left mouse button clicked?
Definition: gfx.cpp:40
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:177
Network lobby window.
Definition: window_type.h:30
The password of the company.
Definition: network_type.h:78
T * Append(uint to_add=1)
Append an item and return it.
Leaf widget.
Definition: widget_type.h:770
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:670
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
void ForceRebuild()
Force that a rebuild is needed.
Data structure for an opened window.
Definition: window_gui.h:271
The game information that is sent from the server to the clients.
Definition: game.h:36
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:36
NWidgetBase * next
Pointer to next widget in container. Managed by parent container widget.
Definition: widget_type.h:180
byte companies_max
Max companies allowed on server.
Definition: game.h:53
static NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1032
old or new savegame
Definition: fileio_type.h:20
void SetFilterTerm(const char *str)
Set the term to filter on.
old or new scenario
Definition: fileio_type.h:21
void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
Assign size and position to the widget.
byte widget_id
The widget that has the pop-up input menu.
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
void ShowMissingContentWindow(const GRFConfig *list)
Show the content list window with all missing grfs from the given list.
void Add(NWidgetBase *wid)
Append widget wid to container.
Definition: widget.cpp:944
List of companies.
NetworkSettings network
settings related to the network
void BuildGUINetworkGameList()
(Re)build the GUI network game list (a.k.a.
bool _is_network_server
Does this client wants to be a network-server?
Definition: network.cpp:60
Only numeric ones.
Definition: string_type.h:28
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
NWidgetBase ** nested_array
Array of pointers into the tree. Do not access directly, use Window::GetWidget() instead.
Definition: window_gui.h:325
NetworkGameList * NetworkGameListAddItem(NetworkAddress address)
Add a new item to the linked gamelist.
Invisible widget that takes some space.
Definition: widget_type.h:79
CompanyID client_playas
As which company is this client playing (CompanyID)
Definition: network_base.h:31
Cancel / OK button.
&#39;Find server&#39; button.
byte companies_on
How many started companies do we have.
Definition: game.h:52
void NetworkUDPSearchGame()
Find all servers.
static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
Show the networklobbywindow with the selected server.
Offset at bottom of a matrix cell.
Definition: window_gui.h:81
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
uint Length() const
Get the number of items in the list.
static NetworkRecvStatus SendCompanyPassword(const char *password)
Set the company password as requested.
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1959
virtual void OnResize()
Called after the window got resized.
void NetworkServerKickClient(ClientID client_id)
Kick a single client.
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
&#39;NewGRF Settings&#39; button.
Selection widget for the above button.
char client_name[NETWORK_CLIENT_NAME_LENGTH]
Name of the client.
Definition: network_base.h:29
Listing GetListing() const
Export current sort conditions.
virtual void OnTick()
Called once per (game) tick.
Header above list of companies.
int ok_button
Widget button of parent window to simulate when pressing OK in OSK.
Scrollbar of matrix.
uint8 max_spectators
maximum amount of spectators
byte clients_max
Max clients allowed on server.
Definition: game.h:51
uint smallest_y
Smallest vertical size of the widget in a filled window.
Definition: widget_type.h:172
uint current_y
Current vertical size (after resizing).
Definition: widget_type.h:175
&#39;Map size&#39; button.
Company information stored at the client side.
Definition: network_gui.h:32
Sort descending.
Definition: window_gui.h:227
Safe the password etc.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
bool _left_button_down
Is left mouse button pressed?
Definition: gfx.cpp:39
Play heightmap button.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
void SetFill(uint fill_x, uint fill_y)
Set the filling of the widget from initial size.
Definition: widget.cpp:839
void DrawServerLine(const NetworkGameList *cur_item, uint y, bool highlight) const
Draw a single server line.
Data stored about a string that can be modified in the GUI.
virtual void OnPaint()
The window must be repainted.
ClientID _network_own_client_id
Our client identifier.
Definition: network.cpp:63
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
void NetworkUDPQueryMasterServer()
Request the the server-list from the master server.
Data structure to convert between Date and triplet (year, month, and day).
Definition: date_type.h:103
bool use_password
Is this server passworded?
Definition: game.h:48
static int CDECL NGameAllowedSorter(NetworkGameList *const *a, NetworkGameList *const *b)
Sort servers by joinability.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:247
Third button in the game list panel.
char connect_to_ip[NETWORK_HOSTNAME_LENGTH]
default for the "Add server" query
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
uint fill_y
Vertical fill stepsize (from initial size, 0 means not resizable).
Definition: widget_type.h:165
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
First company, same as owner.
Definition: company_type.h:24
Simple depressed panel.
Definition: widget_type.h:50
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Window timeout counter.
Definition: window_gui.h:234
static const StringID _connection_types_dropdown[]
Advertisement options in the start server window.
Definition: network_gui.cpp:51
Spacer after last joined server panel.
void ShowGenerateLandscape()
Start with a normal game.
NetworkAddress address
The connection info of the game server.
void SetDParamMaxDigits(uint n, uint count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:121
#define FOR_ALL_CLIENT_INFOS(var)
Iterate over all the clients.
Definition: network_base.h:55
void SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Set additional space (padding) around the widget.
Definition: widget_type.h:149
Center the window.
Definition: window_gui.h:157
&#39;Join game&#39; button.
New game button.
byte clients_on
Current count of clients on server.
Definition: game.h:30
NetworkGameInfo info
The game information of this server.
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1114
&#39;Set password&#39; button.
char server_revision[NETWORK_REVISION_LENGTH]
The version number the server is using (e.g.: &#39;r304&#39; or 0.5.0)
Definition: game.h:44
NetworkGameList * _network_game_list
Game list of this client.
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:65
Baseclass for nested widgets.
Definition: widget_type.h:126
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:499
All flags cleared.
Definition: widget_type.h:428
static int CDECL NGameDateSorter(NetworkGameList *const *a, NetworkGameList *const *b)
Sort servers by current date.
Basic functions/variables used all over the place.
Part of the network protocol handling content distribution.
bool visible[6]
The visible headers.
Definition: network_gui.cpp:96
&#39;Max companies&#39; downarrow.
void NetworkGameListRequery()
Requeries the (game) servers we have not gotten a reply from.
Background of the window.
SmallVector< ClientListAction, 2 > actions
Actions to execute.
virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
Compute the initial position of the window.
int lock_offset
Left offset for lock icon.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
Label for &#39;max companies&#39;.
uint resize_y
Vertical resize step (0 means not resizable).
Definition: widget_type.h:167
Grid of rows and columns.
Definition: widget_type.h:59
&#39;Clients&#39; button.
Panel with game details.
File is being loaded.
Definition: fileio_type.h:51
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
uint pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
&#39;Date&#39; button.
uint8 server_lang
language of the server
NWidgetBase * prev
Pointer to previous widget in container. Managed by parent container widget.
Definition: widget_type.h:181
&#39;Join company&#39; button.
virtual void OnResize()
Called after the window got resized.
static const uint NETWORK_HOSTNAME_LENGTH
The maximum length of the host name, in bytes including &#39;\0&#39;.
Definition: config.h:44
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
void SetSortType(uint8 n_type)
Set the sorttype of the list.
bool Sort(SortFunction *compare)
Sort the list.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition: widget.cpp:658
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
void DeleteWindowByClass(WindowClass cls)
Delete all windows of a given class.
Definition: window.cpp:1150
static const uint8 PC_BLACK
Black palette colour.
Definition: gfx_func.h:207
Background of the window.
Panel with the edit box to enter the search text.
uint32 _network_join_bytes
The number of bytes we already downloaded.
Maximum number of companies.
Definition: company_type.h:25
NetworkGameList * server
Selected server.
Network start server.
Definition: window_type.h:32
static const int WIDGET_LIST_END
indicate the end of widgets&#39; list for vararg functions
Definition: widget_type.h:22
Selection &#39;widget&#39; to hide the NewGRF settings.
The window is a modal child of some other window, meaning the parent is &#39;inactive&#39;.
Definition: window_gui.h:211
uint8 max_companies
maximum amount of companies
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
CompanyID company
Selected company.
void Assign(StringID string)
Render a string into the textbuffer.
Definition: textbuf.cpp:399
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:699
Network status window; Window numbers:
Definition: window_type.h:487
&#39;Max clients&#39; downarrow.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
StringID name
Name of the action to execute.
char map_name[NETWORK_NAME_LENGTH]
Map which is played ["random" for a randomized map].
Definition: game.h:29
StringList _network_host_list
The servers we know.
Definition: network.cpp:68
int blot_offset
Left offset for green/yellow/red compatibility icon.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Label in front of the filter/search edit box.
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:40
byte map_set
Graphical set.
Definition: game.h:56
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1137
static const StringID _lan_internet_types_dropdown[]
Advertisement options in the server list.
Definition: network_gui.cpp:60
Date game_date
Current date.
Definition: game.h:39
static const uint8 PC_GREY
Grey palette colour.
Definition: gfx_func.h:209
static const uint8 PC_DARK_BLUE
Dark blue palette colour.
Definition: gfx_func.h:226
void DrawCompanyIcon(CompanyID cid, int x, int y)
Draw the icon of a company.
The password of the game.
Definition: network_type.h:77
bool online
False if the server did not respond (default status)
&#39;Max clients&#39; text.
void SetResize(uint resize_x, uint resize_y)
Set resize step of the widget.
Definition: widget.cpp:850
ClientList_Action_Proc * proc
Action to execute.
Network join status.
Definition: window_type.h:34
char *const buf
buffer in which text is saved
Definition: textbuf_type.h:34
void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config)
Setup the NewGRF gui.
char client_name[NETWORK_CLIENT_NAME_LENGTH]
name of the player (as client)
Info about the last joined server.
virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)=0
Assign size and position to the widget.
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
static int CDECL NGameYearsSorter(NetworkGameList *const *a, NetworkGameList *const *b)
Sort servers by the number of days the game is running.
NetworkJoinStatus
Status of the clients during joining.
Label for the game name.
Panel with list of games.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition: string.cpp:569
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
void SetFilterState(bool state)
Enable or disable the filter.
int flag_offset
Left offset for langauge flag icon.
void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop)
Launch save/load dialog in the given mode.
Definition: fios_gui.cpp:768
&#39;Start server&#39; button.
Label in front of client name edit box.
Handling of the list of games.
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here...
static void PopupClientList(ClientID client_id, int x, int y)
Show the popup (action list)
Scroll bar.
bool CDECL FilterFunction(const T *, F)
Signature of filter function.
Definition: sortlist_type.h:53
Label for &#39;max clients&#39;.
Sort ascending.
Definition: window_gui.h:226
uint8 max_clients
maximum amount of clients
void SetDParamMaxValue(uint n, uint64 max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:105
ClientID
&#39;Unique&#39; identifier to be given to clients
Definition: network_type.h:43
&#39;Max companies&#39; text.
Vertical container.
Definition: widget_type.h:77
int CDECL SortFunction(const T *, const T *)
Signature of sort function.
Definition: sortlist_type.h:52
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:999
virtual void OnTimeout()
Called when this window&#39;s timeout has been reached.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
NWidgetCore * GetWidgetFromPos(int x, int y)
Retrieve a widget by its position.
Definition: widget.cpp:905
Label in front of connection droplist.
Network window; Window numbers:
Definition: window_type.h:468
&#39;Refresh server&#39; button.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:68
&#39;Find missing NewGRF online&#39; button.
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
&#39;Max spectators&#39; downarrow.
Background of the window.
Popup selection window to chose an action to perform.
Company details.
char default_company_pass[NETWORK_PASSWORD_LENGTH]
default password for new companies in encrypted form
void Draw(const Window *w)
Draw the widgets of the tree.
NetworkGameWidgets
Widgets of the NetworkGameWindow class.
NWidgetBase * head
Pointer to first widget in container.
Definition: widget_type.h:382
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
static void NetworkUDPQueryServer(NetworkAddress *address, bool needs_mutex, bool manually)
Helper function doing the actual work for querying the server.
Definition: network_udp.cpp:75
bool _network_server
network-server is active
Definition: network.cpp:57
Panel of the window.
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:768
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Data structure describing how to show the list (what sort direction and criteria).
Definition: sortlist_type.h:34
Drop down list.
Definition: widget_type.h:70
&#39;Refresh server&#39; button.
uint16 GetPort() const
Get the port.
Definition: address.cpp:39
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:622
void NetworkDisconnect(bool blocking, bool close_admins)
We want to disconnect from the host/clients.
Definition: network.cpp:798
&#39;Max companies&#39; uparrow.
heightmap file
Definition: fileio_type.h:22
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:19
uint32 _network_join_bytes_total
The total number of bytes to download.
Background for editbox to set game name.
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
char last_host[NETWORK_HOSTNAME_LENGTH]
IP address of the last joined server.
void AddAction(StringID name, ClientList_Action_Proc *proc)
Add an action to the list of actions to execute.
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
Company password query; Window numbers:
Definition: window_type.h:499
&#39;Spectate game&#39; button.
static const uint NETWORK_NAME_LENGTH
The maximum length of the server name and map name, in bytes including &#39;\0&#39;.
Definition: config.h:42
static const uint NETWORK_PASSWORD_LENGTH
The maximum length of the password, in bytes including &#39;\0&#39; (must be >= NETWORK_SERVER_ID_LENGTH) ...
Definition: config.h:47
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:983
Close the window without changing anything.
&#39;Name&#39; button.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
QueryString name_editbox
Client name editbox.
bool IsDescSortOrder() const
Check if the sort order is descending.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Full blown container to make it behave exactly as we want :)
Definition: network_gui.cpp:94
NetworkGameList * server
selected server
static const uint MAX_MAP_SIZE
Maximal map size = 4096.
Definition: map_type.h:67
int32 WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:695
void SetCapacityFromWidget(Window *w, int widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget. ...
Definition: widget.cpp:1973
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:84
NetworkPasswordType
The type of password we&#39;re asking for.
Definition: network_type.h:76
The passed event is handled.
Definition: window_type.h:702
void ScrollToSelectedServer()
Scroll the list up or down to the currently selected server.
Text is written right-to-left by default.
Definition: strings_type.h:26
void ClientList_Action_Proc(const NetworkClientInfo *ci)
Prototype for ClientList actions.
Owner
Enum for all companies/owners.
Definition: company_type.h:20
QueryString name_editbox
Server name editbox.
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it&#39;s client-identifier.
Definition: network.cpp:126
Find a place automatically.
Definition: window_gui.h:156
(Toggle) Button with image
Definition: widget_type.h:52
GUIGameServerList servers
list with game servers.
char server_password[NETWORK_PASSWORD_LENGTH]
password for joining this server
&#39;Connection&#39; droplist button.
const char * NetworkChangeCompanyPassword(CompanyID company_id, const char *password)
Change the company password of a given company.
Definition: network.cpp:174
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
uint8 _network_join_waiting
The number of clients waiting in front of us.
virtual void OnMouseLoop()
Called for every mouse loop run, which is at least once per (game) tick.
GRFConfig * grfconfig
List of NewGRF files used.
Definition: game.h:37
static void QSortT(T *base, uint num, int(CDECL *comparator)(const T *, const T *), bool desc=false)
Type safe qsort()
Definition: sort_func.hpp:28
uint32 WChar
Type for wide characters, i.e.
Definition: string_type.h:35
Container for actions that can be executed.
Scrollbar * vscroll
vertical scrollbar of the list of servers
void ConvertDateToYMD(Date date, YearMonthDay *ymd)
Converts a Date to a Year, Month & Day.
Definition: date.cpp:94
void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen)
Resize the window.
Definition: window.cpp:2116
Label in front of the password field.
An invalid company.
Definition: company_type.h:32
virtual void SetDirty(const Window *w) const
Mark the widget as &#39;dirty&#39; (in need of repaint).
Definition: widget.cpp:775
Window white border counter bit mask.
Definition: window_gui.h:242
&#39;Cancel&#39; button.
Send message/notice to everyone playing the same company (Team)
Definition: network_type.h:84
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1095
uint fill_x
Horizontal fill stepsize (from initial size, 0 means not resizable).
Definition: widget_type.h:164
void SetupSmallestSize(Window *w, bool init_array)
Compute smallest size needed by the widget.
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:429
bool IsEmpty() const
Check whether any filter words were entered.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
&#39;Connection type&#39; droplist button.
void UpdateListPos()
Set this->list_pos to match this->server.
static int CDECL NGameClientSorter(NetworkGameList *const *a, NetworkGameList *const *b)
Sort servers by the amount of clients online on a server.
void GetAddressAsString(char *buffer, const char *last, bool with_family=true)
Get the address as a string, e.g.
Definition: address.cpp:81
byte spectators_on
How many spectators do we have?
Definition: game.h:54
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:833
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1076
bool compatible
Can we connect to this server or not? (based on server_revision and grf_match.
Definition: game.h:47
void ShowNetworkChatQueryWindow(DestType type, int dest)
Show the chat window.
static const SpriteID SPR_FLAGS_BASE
Flags sprites (in same order as enum NetworkLanguage)
Definition: sprites.h:284
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3220
(Toggle) Button with text
Definition: widget_type.h:55
NetworkCompanyInfo * GetLobbyCompanyInfo(CompanyID company)
Get the company information of a given company to fill for the lobby.
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:631
&#39;Max spectators&#39; uparrow.
uint8 SortType() const
Get the sorttype of the list.
Definition: sortlist_type.h:97
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
Base class for a &#39;real&#39; widget.
Definition: widget_type.h:284