OpenTTD
network_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
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 #include "../guitimer_func.h"
35 
36 #include "../widgets/network_widget.h"
37 
38 #include "table/strings.h"
39 #include "../table/sprites.h"
40 
41 #include "../stringfilter_type.h"
42 
43 #include "../safeguards.h"
44 
45 
46 static void ShowNetworkStartServerWindow();
47 static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
48 
53  STR_NETWORK_START_SERVER_UNADVERTISED,
54  STR_NETWORK_START_SERVER_ADVERTISED,
56 };
57 
62  STR_NETWORK_SERVER_LIST_ADVERTISED_NO,
63  STR_NETWORK_SERVER_LIST_ADVERTISED_YES,
65 };
66 
67 static StringID _language_dropdown[NETLANG_COUNT + 1] = {STR_NULL};
68 
69 void SortNetworkLanguages()
70 {
71  /* Init the strings */
72  if (_language_dropdown[0] == STR_NULL) {
73  for (int i = 0; i < NETLANG_COUNT; i++) _language_dropdown[i] = STR_NETWORK_LANG_ANY + i;
74  _language_dropdown[NETLANG_COUNT] = INVALID_STRING_ID;
75  }
76 
77  /* Sort the strings (we don't move 'any' and the 'invalid' one) */
78  QSortT(_language_dropdown + 1, NETLANG_COUNT - 1, &StringIDSorter);
79 }
80 
86 {
88 }
89 
91 typedef uint16 ServerListPosition;
92 static const ServerListPosition SLP_INVALID = 0xFFFF;
93 
96  static const uint MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER = 150;
97  bool visible[6];
98 public:
100  {
101  NWidgetLeaf *leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME_TOOLTIP);
102  leaf->SetResize(1, 0);
103  leaf->SetFill(1, 0);
104  this->Add(leaf);
105 
106  this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_CLIENTS, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION_TOOLTIP));
107  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));
108  this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_DATE, STR_NETWORK_SERVER_LIST_DATE_CAPTION, STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP));
109  this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_YEARS, STR_NETWORK_SERVER_LIST_YEARS_CAPTION, STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP));
110 
111  leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_INFO, STR_EMPTY, STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP);
112  leaf->SetMinimalSize(14 + GetSpriteSize(SPR_LOCK).width + GetSpriteSize(SPR_BLOT).width + GetSpriteSize(SPR_FLAGS_BASE).width, 12);
113  leaf->SetFill(0, 1);
114  this->Add(leaf);
115 
116  /* First and last are always visible, the rest is implicitly zeroed */
117  this->visible[0] = true;
118  *lastof(this->visible) = true;
119  }
120 
121  void SetupSmallestSize(Window *w, bool init_array)
122  {
123  /* Oh yeah, we ought to be findable! */
124  w->nested_array[WID_NG_HEADER] = this;
125 
126  this->smallest_y = 0; // Biggest child.
127  this->fill_x = 1;
128  this->fill_y = 0;
129  this->resize_x = 1; // We only resize in this direction
130  this->resize_y = 0; // We never resize in this direction
131 
132  /* First initialise some variables... */
133  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
134  child_wid->SetupSmallestSize(w, init_array);
135  this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
136  }
137 
138  /* ... then in a second pass make sure the 'current' sizes are set. Won't change for most widgets. */
139  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
140  child_wid->current_x = child_wid->smallest_x;
141  child_wid->current_y = this->smallest_y;
142  }
143 
144  this->smallest_x = this->head->smallest_x + this->tail->smallest_x; // First and last are always shown, rest not
145  }
146 
147  void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
148  {
149  assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
150 
151  this->pos_x = x;
152  this->pos_y = y;
153  this->current_x = given_width;
154  this->current_y = given_height;
155 
156  given_width -= this->tail->smallest_x;
157  NWidgetBase *child_wid = this->head->next;
158  /* The first and last widget are always visible, determine which other should be visible */
159  for (uint i = 1; i < lengthof(this->visible) - 1; i++) {
160  if (given_width > MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER + child_wid->smallest_x && this->visible[i - 1]) {
161  this->visible[i] = true;
162  given_width -= child_wid->smallest_x;
163  } else {
164  this->visible[i] = false;
165  }
166  child_wid = child_wid->next;
167  }
168 
169  /* All remaining space goes to the first (name) widget */
170  this->head->current_x = given_width;
171 
172  /* Now assign the widgets to their rightful place */
173  uint position = 0; // Place to put next child relative to origin of the container.
174  uint i = rtl ? lengthof(this->visible) - 1 : 0;
175  child_wid = rtl ? this->tail : this->head;
176  while (child_wid != NULL) {
177  if (this->visible[i]) {
178  child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
179  position += child_wid->current_x;
180  }
181 
182  child_wid = rtl ? child_wid->prev : child_wid->next;
183  i += rtl ? -1 : 1;
184  }
185  }
186 
187  /* virtual */ void Draw(const Window *w)
188  {
189  int i = 0;
190  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
191  if (!this->visible[i++]) continue;
192 
193  child_wid->Draw(w);
194  }
195  }
196 
197  /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
198  {
199  if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
200 
201  int i = 0;
202  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
203  if (!this->visible[i++]) continue;
204  NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
205  if (nwid != NULL) return nwid;
206  }
207  return NULL;
208  }
209 
216  {
217  assert((uint)(widget - WID_NG_NAME) < lengthof(this->visible));
218  return this->visible[widget - WID_NG_NAME];
219  }
220 };
221 
222 class NetworkGameWindow : public Window {
223 protected:
224  /* Runtime saved values */
225  static Listing last_sorting;
226 
227  /* Constants for sorting servers */
228  static GUIGameServerList::SortFunction * const sorter_funcs[];
229  static GUIGameServerList::FilterFunction * const filter_funcs[];
230 
234  ServerListPosition list_pos;
239 
243 
250  {
251  if (!this->servers.NeedRebuild()) return;
252 
253  /* Create temporary array of games to use for listing */
254  this->servers.Clear();
255 
256  for (NetworkGameList *ngl = _network_game_list; ngl != NULL; ngl = ngl->next) {
257  *this->servers.Append() = ngl;
258  }
259 
260  /* Apply the filter condition immediately, if a search string has been provided. */
261  StringFilter sf;
262  sf.SetFilterTerm(this->filter_editbox.text.buf);
263 
264  if (!sf.IsEmpty()) {
265  this->servers.SetFilterState(true);
266  this->servers.Filter(sf);
267  } else {
268  this->servers.SetFilterState(false);
269  }
270 
271  this->servers.Compact();
272  this->servers.RebuildDone();
273  this->vscroll->SetCount(this->servers.Length());
274 
275  /* Sort the list of network games as requested. */
276  this->servers.Sort();
277  this->UpdateListPos();
278  }
279 
281  static int CDECL NGameNameSorter(NetworkGameList * const *a, NetworkGameList * const *b)
282  {
283  int r = strnatcmp((*a)->info.server_name, (*b)->info.server_name, true); // Sort by name (natural sorting).
284  return r == 0 ? (*a)->address.CompareTo((*b)->address) : r;
285  }
286 
292  static int CDECL NGameClientSorter(NetworkGameList * const *a, NetworkGameList * const *b)
293  {
294  /* Reverse as per default we are interested in most-clients first */
295  int r = (*a)->info.clients_on - (*b)->info.clients_on;
296 
297  if (r == 0) r = (*a)->info.clients_max - (*b)->info.clients_max;
298  if (r == 0) r = NGameNameSorter(a, b);
299 
300  return r;
301  }
302 
304  static int CDECL NGameMapSizeSorter(NetworkGameList * const *a, NetworkGameList * const *b)
305  {
306  /* Sort by the area of the map. */
307  int r = ((*a)->info.map_height) * ((*a)->info.map_width) - ((*b)->info.map_height) * ((*b)->info.map_width);
308 
309  if (r == 0) r = (*a)->info.map_width - (*b)->info.map_width;
310  return (r != 0) ? r : NGameClientSorter(a, b);
311  }
312 
314  static int CDECL NGameDateSorter(NetworkGameList * const *a, NetworkGameList * const *b)
315  {
316  int r = (*a)->info.game_date - (*b)->info.game_date;
317  return (r != 0) ? r : NGameClientSorter(a, b);
318  }
319 
321  static int CDECL NGameYearsSorter(NetworkGameList * const *a, NetworkGameList * const *b)
322  {
323  int r = (*a)->info.game_date - (*a)->info.start_date - (*b)->info.game_date + (*b)->info.start_date;
324  return (r != 0) ? r : NGameDateSorter(a, b);
325  }
326 
331  static int CDECL NGameAllowedSorter(NetworkGameList * const *a, NetworkGameList * const *b)
332  {
333  /* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */
334  int r = StrEmpty((*a)->info.server_revision) - StrEmpty((*b)->info.server_revision);
335 
336  /* Reverse default as we are interested in version-compatible clients first */
337  if (r == 0) r = (*b)->info.version_compatible - (*a)->info.version_compatible;
338  /* The version-compatible ones are then sorted with NewGRF compatible first, incompatible last */
339  if (r == 0) r = (*b)->info.compatible - (*a)->info.compatible;
340  /* Passworded servers should be below unpassworded servers */
341  if (r == 0) r = (*a)->info.use_password - (*b)->info.use_password;
342  /* Finally sort on the number of clients of the server */
343  if (r == 0) r = -NGameClientSorter(a, b);
344 
345  return r;
346  }
347 
350  {
351  if (this->servers.Sort()) this->UpdateListPos();
352  }
353 
356  {
357  this->list_pos = SLP_INVALID;
358  for (uint i = 0; i != this->servers.Length(); i++) {
359  if (this->servers[i] == this->server) {
360  this->list_pos = i;
361  break;
362  }
363  }
364  }
365 
366  static bool CDECL NGameSearchFilter(NetworkGameList * const *item, StringFilter &sf)
367  {
368  assert(item != NULL);
369  assert((*item) != NULL);
370 
371  sf.ResetState();
372  sf.AddLine((*item)->info.server_name);
373  return sf.GetState();
374  }
375 
382  void DrawServerLine(const NetworkGameList *cur_item, uint y, bool highlight) const
383  {
384  const NWidgetBase *nwi_name = this->GetWidget<NWidgetBase>(WID_NG_NAME);
385  const NWidgetBase *nwi_info = this->GetWidget<NWidgetBase>(WID_NG_INFO);
386 
387  /* show highlighted item with a different colour */
388  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);
389 
390  /* offsets to vertically centre text and icons */
391  int text_y_offset = (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2 + 1;
392  int icon_y_offset = (this->resize.step_height - GetSpriteSize(SPR_BLOT).height) / 2;
393 
394  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);
395 
396  /* only draw details if the server is online */
397  if (cur_item->online) {
398  const NWidgetServerListHeader *nwi_header = this->GetWidget<NWidgetServerListHeader>(WID_NG_HEADER);
399 
400  if (nwi_header->IsWidgetVisible(WID_NG_CLIENTS)) {
401  const NWidgetBase *nwi_clients = this->GetWidget<NWidgetBase>(WID_NG_CLIENTS);
402  SetDParam(0, cur_item->info.clients_on);
403  SetDParam(1, cur_item->info.clients_max);
404  SetDParam(2, cur_item->info.companies_on);
405  SetDParam(3, cur_item->info.companies_max);
406  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);
407  }
408 
409  if (nwi_header->IsWidgetVisible(WID_NG_MAPSIZE)) {
410  /* map size */
411  const NWidgetBase *nwi_mapsize = this->GetWidget<NWidgetBase>(WID_NG_MAPSIZE);
412  SetDParam(0, cur_item->info.map_width);
413  SetDParam(1, cur_item->info.map_height);
414  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);
415  }
416 
417  if (nwi_header->IsWidgetVisible(WID_NG_DATE)) {
418  /* current date */
419  const NWidgetBase *nwi_date = this->GetWidget<NWidgetBase>(WID_NG_DATE);
420  YearMonthDay ymd;
421  ConvertDateToYMD(cur_item->info.game_date, &ymd);
422  SetDParam(0, ymd.year);
423  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);
424  }
425 
426  if (nwi_header->IsWidgetVisible(WID_NG_YEARS)) {
427  /* number of years the game is running */
428  const NWidgetBase *nwi_years = this->GetWidget<NWidgetBase>(WID_NG_YEARS);
429  YearMonthDay ymd_cur, ymd_start;
430  ConvertDateToYMD(cur_item->info.game_date, &ymd_cur);
431  ConvertDateToYMD(cur_item->info.start_date, &ymd_start);
432  SetDParam(0, ymd_cur.year - ymd_start.year);
433  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);
434  }
435 
436  /* draw a lock if the server is password protected */
437  if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, nwi_info->pos_x + this->lock_offset, y + icon_y_offset - 1);
438 
439  /* draw red or green icon, depending on compatibility with server */
440  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);
441 
442  /* draw flag according to server language */
443  DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, nwi_info->pos_x + this->flag_offset, y + icon_y_offset);
444  }
445  }
446 
455  {
456  if (this->list_pos == SLP_INVALID) return; // no server selected
457  this->vscroll->ScrollTowards(this->list_pos);
458  }
459 
460 public:
461  NetworkGameWindow(WindowDesc *desc) : Window(desc), name_editbox(NETWORK_CLIENT_NAME_LENGTH), filter_editbox(120)
462  {
463  this->list_pos = SLP_INVALID;
464  this->server = NULL;
465 
466  this->lock_offset = 5;
467  this->blot_offset = this->lock_offset + 3 + GetSpriteSize(SPR_LOCK).width;
468  this->flag_offset = this->blot_offset + 2 + GetSpriteSize(SPR_BLOT).width;
469 
470  this->CreateNestedTree();
471  this->vscroll = this->GetScrollbar(WID_NG_SCROLLBAR);
472  this->FinishInitNested(WN_NETWORK_WINDOW_GAME);
473 
474  this->querystrings[WID_NG_CLIENT] = &this->name_editbox;
475  this->name_editbox.text.Assign(_settings_client.network.client_name);
476 
477  this->querystrings[WID_NG_FILTER] = &this->filter_editbox;
478  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
479  this->SetFocusedWidget(WID_NG_FILTER);
480 
482  this->server = this->last_joined;
483  if (this->last_joined != NULL) NetworkUDPQueryServer(this->last_joined->address);
484 
485  this->requery_timer.SetInterval(MILLISECONDS_PER_TICK);
486 
487  this->servers.SetListing(this->last_sorting);
488  this->servers.SetSortFuncs(this->sorter_funcs);
489  this->servers.SetFilterFuncs(this->filter_funcs);
490  this->servers.ForceRebuild();
491  }
492 
494  {
495  this->last_sorting = this->servers.GetListing();
496  }
497 
498  virtual void SetStringParameters(int widget) const
499  {
500  switch (widget) {
501  case WID_NG_CONN_BTN:
503  break;
504  }
505  }
506 
507  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
508  {
509  switch (widget) {
510  case WID_NG_CONN_BTN:
512  size->width += padding.width;
513  size->height += padding.height;
514  break;
515 
516  case WID_NG_MATRIX:
517  resize->height = WD_MATRIX_TOP + max(GetSpriteSize(SPR_BLOT).height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM;
518  size->height = 10 * resize->height;
519  break;
520 
521  case WID_NG_LASTJOINED:
522  size->height = WD_MATRIX_TOP + max(GetSpriteSize(SPR_BLOT).height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_BOTTOM;
523  break;
524 
526  size->width = NWidgetScrollbar::GetVerticalDimension().width;
527  break;
528 
529  case WID_NG_NAME:
530  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
531  break;
532 
533  case WID_NG_CLIENTS:
534  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
539  *size = maxdim(*size, GetStringBoundingBox(STR_NETWORK_SERVER_LIST_GENERAL_ONLINE));
540  break;
541 
542  case WID_NG_MAPSIZE:
543  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
546  *size = maxdim(*size, GetStringBoundingBox(STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT));
547  break;
548 
549  case WID_NG_DATE:
550  case WID_NG_YEARS:
551  size->width += 2 * Window::SortButtonWidth(); // Make space for the arrow
552  SetDParamMaxValue(0, 5);
553  *size = maxdim(*size, GetStringBoundingBox(STR_JUST_INT));
554  break;
555 
557  size->height = 20 + 12 * FONT_HEIGHT_NORMAL;
558  break;
559  }
560  }
561 
562  virtual void DrawWidget(const Rect &r, int widget) const
563  {
564  switch (widget) {
565  case WID_NG_MATRIX: {
566  uint16 y = r.top;
567 
568  const int max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), (int)this->servers.Length());
569 
570  for (int i = this->vscroll->GetPosition(); i < max; ++i) {
571  const NetworkGameList *ngl = this->servers[i];
572  this->DrawServerLine(ngl, y, ngl == this->server);
573  y += this->resize.step_height;
574  }
575  break;
576  }
577 
578  case WID_NG_LASTJOINED:
579  /* Draw the last joined server, if any */
580  if (this->last_joined != NULL) this->DrawServerLine(this->last_joined, r.top, this->last_joined == this->server);
581  break;
582 
583  case WID_NG_DETAILS:
584  this->DrawDetails(r);
585  break;
586 
587  case WID_NG_NAME:
588  case WID_NG_CLIENTS:
589  case WID_NG_MAPSIZE:
590  case WID_NG_DATE:
591  case WID_NG_YEARS:
592  case WID_NG_INFO:
593  if (widget - WID_NG_NAME == this->servers.SortType()) this->DrawSortButtonState(widget, this->servers.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
594  break;
595  }
596  }
597 
598 
599  virtual void OnPaint()
600  {
601  if (this->servers.NeedRebuild()) {
602  this->BuildGUINetworkGameList();
603  }
604  if (this->servers.NeedResort()) {
605  this->SortNetworkGameList();
606  }
607 
608  NetworkGameList *sel = this->server;
609  /* 'Refresh' button invisible if no server selected */
610  this->SetWidgetDisabledState(WID_NG_REFRESH, sel == NULL);
611  /* 'Join' button disabling conditions */
612  this->SetWidgetDisabledState(WID_NG_JOIN, sel == NULL || // no Selected Server
613  !sel->online || // Server offline
614  sel->info.clients_on >= sel->info.clients_max || // Server full
615  !sel->info.compatible); // Revision mismatch
616 
617  /* 'NewGRF Settings' button invisible if no NewGRF is used */
618  this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_SEL)->SetDisplayedPlane(sel == NULL || !sel->online || sel->info.grfconfig == NULL);
619  this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_MISSING_SEL)->SetDisplayedPlane(sel == NULL || !sel->online || sel->info.grfconfig == NULL || !sel->info.version_compatible || sel->info.compatible);
620 
621  this->DrawWidgets();
622  }
623 
624  void DrawDetails(const Rect &r) const
625  {
626  NetworkGameList *sel = this->server;
627 
628  const int detail_height = 6 + 8 + 6 + 3 * FONT_HEIGHT_NORMAL;
629 
630  /* Draw the right menu */
631  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + detail_height - 1, PC_DARK_BLUE);
632  if (sel == NULL) {
633  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);
634  } else if (!sel->online) {
635  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
636 
637  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
638  } else { // show game info
639 
640  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);
641  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
642  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
643 
644  uint16 y = r.top + detail_height + 4;
645 
646  SetDParam(0, sel->info.clients_on);
647  SetDParam(1, sel->info.clients_max);
648  SetDParam(2, sel->info.companies_on);
649  SetDParam(3, sel->info.companies_max);
650  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CLIENTS);
651  y += FONT_HEIGHT_NORMAL;
652 
653  SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
654  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_LANGUAGE); // server language
655  y += FONT_HEIGHT_NORMAL;
656 
657  SetDParam(0, STR_CHEAT_SWITCH_CLIMATE_TEMPERATE_LANDSCAPE + sel->info.map_set);
658  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_LANDSCAPE); // landscape
659  y += FONT_HEIGHT_NORMAL;
660 
661  SetDParam(0, sel->info.map_width);
662  SetDParam(1, sel->info.map_height);
663  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_MAP_SIZE); // map size
664  y += FONT_HEIGHT_NORMAL;
665 
667  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_VERSION); // server version
668  y += FONT_HEIGHT_NORMAL;
669 
671  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_SERVER_ADDRESS); // server address
672  y += FONT_HEIGHT_NORMAL;
673 
674  SetDParam(0, sel->info.start_date);
675  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_START_DATE); // start date
676  y += FONT_HEIGHT_NORMAL;
677 
678  SetDParam(0, sel->info.game_date);
679  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CURRENT_DATE); // current date
680  y += FONT_HEIGHT_NORMAL;
681 
682  y += WD_PAR_VSEP_NORMAL;
683 
684  if (!sel->info.compatible) {
685  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
686  } else if (sel->info.clients_on == sel->info.clients_max) {
687  /* Show: server full, when clients_on == max_clients */
688  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
689  } else if (sel->info.use_password) {
690  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_PASSWORD, TC_FROMSTRING, SA_HOR_CENTER); // password warning
691  }
692  }
693  }
694 
695  virtual void OnClick(Point pt, int widget, int click_count)
696  {
697  switch (widget) {
698  case WID_NG_CANCEL: // Cancel button
700  break;
701 
702  case WID_NG_CONN_BTN: // 'Connection' droplist
703  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
704  break;
705 
706  case WID_NG_NAME: // Sort by name
707  case WID_NG_CLIENTS: // Sort by connected clients
708  case WID_NG_MAPSIZE: // Sort by map size
709  case WID_NG_DATE: // Sort by date
710  case WID_NG_YEARS: // Sort by years
711  case WID_NG_INFO: // Connectivity (green dot)
712  if (this->servers.SortType() == widget - WID_NG_NAME) {
713  this->servers.ToggleSortOrder();
714  if (this->list_pos != SLP_INVALID) this->list_pos = this->servers.Length() - this->list_pos - 1;
715  } else {
716  this->servers.SetSortType(widget - WID_NG_NAME);
717  this->servers.ForceResort();
718  this->SortNetworkGameList();
719  }
720  this->ScrollToSelectedServer();
721  this->SetDirty();
722  break;
723 
724  case WID_NG_MATRIX: { // Show available network games
725  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NG_MATRIX);
726  this->server = (id_v < this->servers.Length()) ? this->servers[id_v] : NULL;
727  this->list_pos = (server == NULL) ? SLP_INVALID : id_v;
728  this->SetDirty();
729 
730  /* FIXME the disabling should go into some InvalidateData, which is called instead of the SetDirty */
731  if (click_count > 1 && !this->IsWidgetDisabled(WID_NG_JOIN)) this->OnClick(pt, WID_NG_JOIN, 1);
732  break;
733  }
734 
735  case WID_NG_LASTJOINED: {
736  if (this->last_joined != NULL) {
737  this->server = this->last_joined;
738 
739  /* search the position of the newly selected server */
740  this->UpdateListPos();
741  this->ScrollToSelectedServer();
742  this->SetDirty();
743 
744  /* FIXME the disabling should go into some InvalidateData, which is called instead of the SetDirty */
745  if (click_count > 1 && !this->IsWidgetDisabled(WID_NG_JOIN)) this->OnClick(pt, WID_NG_JOIN, 1);
746  }
747  break;
748  }
749 
750  case WID_NG_FIND: // Find server automatically
752  case 0: NetworkUDPSearchGame(); break;
753  case 1: NetworkUDPQueryMasterServer(); break;
754  }
755  break;
756 
757  case WID_NG_ADD: // Add a server
760  STR_JUST_RAW_STRING,
761  STR_NETWORK_SERVER_LIST_ENTER_IP,
762  NETWORK_HOSTNAME_LENGTH, // maximum number of characters including '\0'
764  break;
765 
766  case WID_NG_START: // Start server
767  ShowNetworkStartServerWindow();
768  break;
769 
770  case WID_NG_JOIN: // Join Game
771  if (this->server != NULL) {
772  seprintf(_settings_client.network.last_host, lastof(_settings_client.network.last_host), "%s", this->server->address.GetHostname());
774  ShowNetworkLobbyWindow(this->server);
775  }
776  break;
777 
778  case WID_NG_REFRESH: // Refresh
779  if (this->server != NULL) NetworkUDPQueryServer(this->server->address);
780  break;
781 
782  case WID_NG_NEWGRF: // NewGRF Settings
783  if (this->server != NULL) ShowNewGRFSettings(false, false, false, &this->server->info.grfconfig);
784  break;
785 
786  case WID_NG_NEWGRF_MISSING: // Find missing content online
787  if (this->server != NULL) ShowMissingContentWindow(this->server->info.grfconfig);
788  break;
789  }
790  }
791 
792  virtual void OnDropdownSelect(int widget, int index)
793  {
794  switch (widget) {
795  case WID_NG_CONN_BTN:
797  break;
798 
799  default:
800  NOT_REACHED();
801  }
802 
803  this->SetDirty();
804  }
805 
811  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
812  {
813  this->servers.ForceRebuild();
814  this->SetDirty();
815  }
816 
817  virtual EventState OnKeyPress(WChar key, uint16 keycode)
818  {
819  EventState state = ES_NOT_HANDLED;
820 
821  /* handle up, down, pageup, pagedown, home and end */
822  if (keycode == WKC_UP || keycode == WKC_DOWN || keycode == WKC_PAGEUP || keycode == WKC_PAGEDOWN || keycode == WKC_HOME || keycode == WKC_END) {
823  if (this->servers.Length() == 0) return ES_HANDLED;
824  switch (keycode) {
825  case WKC_UP:
826  /* scroll up by one */
827  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
828  if (this->list_pos > 0) this->list_pos--;
829  break;
830  case WKC_DOWN:
831  /* scroll down by one */
832  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
833  if (this->list_pos < this->servers.Length() - 1) this->list_pos++;
834  break;
835  case WKC_PAGEUP:
836  /* scroll up a page */
837  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
838  this->list_pos = (this->list_pos < this->vscroll->GetCapacity()) ? 0 : this->list_pos - this->vscroll->GetCapacity();
839  break;
840  case WKC_PAGEDOWN:
841  /* scroll down a page */
842  if (this->list_pos == SLP_INVALID) return ES_HANDLED;
843  this->list_pos = min(this->list_pos + this->vscroll->GetCapacity(), (int)this->servers.Length() - 1);
844  break;
845  case WKC_HOME:
846  /* jump to beginning */
847  this->list_pos = 0;
848  break;
849  case WKC_END:
850  /* jump to end */
851  this->list_pos = this->servers.Length() - 1;
852  break;
853  default: NOT_REACHED();
854  }
855 
856  this->server = this->servers[this->list_pos];
857 
858  /* Scroll to the new server if it is outside the current range. */
859  this->ScrollToSelectedServer();
860 
861  /* redraw window */
862  this->SetDirty();
863  return ES_HANDLED;
864  }
865 
866  if (this->server != NULL) {
867  if (keycode == WKC_DELETE) { // Press 'delete' to remove servers
868  NetworkGameListRemoveItem(this->server);
869  if (this->server == this->last_joined) this->last_joined = NULL;
870  this->server = NULL;
871  this->list_pos = SLP_INVALID;
872  }
873  }
874 
875  return state;
876  }
877 
878  virtual void OnEditboxChanged(int wid)
879  {
880  switch (wid) {
881  case WID_NG_FILTER: {
882  this->servers.ForceRebuild();
883  this->BuildGUINetworkGameList();
884  this->ScrollToSelectedServer();
885  this->SetDirty();
886  break;
887  }
888 
889  case WID_NG_CLIENT:
890  /* Make sure the name does not start with a space, so TAB completion works */
891  if (!StrEmpty(this->name_editbox.text.buf) && this->name_editbox.text.buf[0] != ' ') {
893  } else {
895  }
896  break;
897  }
898  }
899 
900  virtual void OnQueryTextFinished(char *str)
901  {
902  if (!StrEmpty(str)) NetworkAddServer(str);
903  }
904 
905  virtual void OnResize()
906  {
907  this->vscroll->SetCapacityFromWidget(this, WID_NG_MATRIX);
908  }
909 
910  virtual void OnRealtimeTick(uint delta_ms)
911  {
912  if (!this->requery_timer.Elapsed(delta_ms)) return;
913  this->requery_timer.SetInterval(MILLISECONDS_PER_TICK);
914 
916  }
917 };
918 
919 Listing NetworkGameWindow::last_sorting = {false, 5};
920 GUIGameServerList::SortFunction * const NetworkGameWindow::sorter_funcs[] = {
921  &NGameNameSorter,
922  &NGameClientSorter,
923  &NGameMapSizeSorter,
924  &NGameDateSorter,
925  &NGameYearsSorter,
926  &NGameAllowedSorter
927 };
928 
929 GUIGameServerList::FilterFunction * const NetworkGameWindow::filter_funcs[] = {
930  &NGameSearchFilter
931 };
932 
933 static NWidgetBase *MakeResizableHeader(int *biggest_index)
934 {
935  *biggest_index = max<int>(*biggest_index, WID_NG_INFO);
936  return new NWidgetServerListHeader();
937 }
938 
939 static const NWidgetPart _nested_network_game_widgets[] = {
940  /* TOP */
942  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
943  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_NETWORK_SERVER_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
944  NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
945  EndContainer(),
946  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_MAIN),
947  NWidget(NWID_VERTICAL), SetPIP(10, 7, 0),
948  NWidget(NWID_HORIZONTAL), SetPIP(10, 7, 10),
949  /* LEFT SIDE */
950  NWidget(NWID_VERTICAL), SetPIP(0, 7, 0),
951  NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
952  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CONNECTION), SetDataTip(STR_NETWORK_SERVER_LIST_ADVERTISED, STR_NULL),
953  NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NG_CONN_BTN),
954  SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
955  NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
956  EndContainer(),
957  NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
958  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_FILTER_LABEL), SetDataTip(STR_LIST_FILTER_TITLE, STR_NULL),
959  NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_FILTER), SetMinimalSize(251, 12), SetFill(1, 0), SetResize(1, 0),
960  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
961  EndContainer(),
964  NWidgetFunction(MakeResizableHeader),
965  NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, WID_NG_MATRIX), SetResize(1, 1), SetFill(1, 0),
966  SetMatrixDataTip(1, 0, STR_NETWORK_SERVER_LIST_CLICK_GAME_TO_SELECT), SetScrollbar(WID_NG_SCROLLBAR),
967  EndContainer(),
968  NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NG_SCROLLBAR),
969  EndContainer(),
971  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED_LABEL), SetFill(1, 0),
972  SetDataTip(STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER, STR_NULL), SetResize(1, 0),
974  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED), SetFill(1, 0), SetResize(1, 0),
975  SetDataTip(0x0, STR_NETWORK_SERVER_LIST_CLICK_TO_SELECT_LAST),
976  EndContainer(),
977  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_LASTJOINED_SPACER), SetFill(0, 0),
978  EndContainer(),
979  EndContainer(),
980  EndContainer(),
981  /* RIGHT SIDE */
982  NWidget(NWID_VERTICAL), SetPIP(0, 7, 0),
983  NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
984  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CLIENT_LABEL), SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME, STR_NULL),
985  NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_CLIENT), SetMinimalSize(151, 12), SetFill(1, 0), SetResize(1, 0),
986  SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE, STR_NETWORK_SERVER_LIST_ENTER_NAME_TOOLTIP),
987  EndContainer(),
988  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_DETAILS),
990  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
993  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),
994  NWidget(NWID_SPACER), SetFill(1, 0),
995  EndContainer(),
996  EndContainer(),
998  NWidget(NWID_SPACER), SetFill(1, 0),
999  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NG_NEWGRF_SEL),
1000  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF), SetFill(1, 0), SetDataTip(STR_INTRO_NEWGRF_SETTINGS, STR_NULL),
1001  NWidget(NWID_SPACER), SetFill(1, 0),
1002  EndContainer(),
1003  EndContainer(),
1005  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_JOIN), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_JOIN_GAME, STR_NULL),
1006  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_REFRESH), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_REFRESH, STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP),
1007  EndContainer(),
1008  EndContainer(),
1009  EndContainer(),
1010  EndContainer(),
1011  EndContainer(),
1012  /* BOTTOM */
1016  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),
1017  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),
1018  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),
1019  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_CANCEL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
1020  EndContainer(),
1021  NWidget(NWID_SPACER), SetMinimalSize(0, 6), SetResize(1, 0), SetFill(1, 0),
1022  EndContainer(),
1024  NWidget(NWID_SPACER), SetFill(0, 1),
1025  NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE),
1026  EndContainer(),
1027  EndContainer(),
1028  EndContainer(),
1029  EndContainer(),
1030 };
1031 
1032 static WindowDesc _network_game_window_desc(
1033  WDP_CENTER, "list_servers", 1000, 730,
1035  0,
1036  _nested_network_game_widgets, lengthof(_nested_network_game_widgets)
1037 );
1038 
1039 void ShowNetworkGameWindow()
1040 {
1041  static bool first = true;
1044 
1045  /* Only show once */
1046  if (first) {
1047  first = false;
1048  /* Add all servers from the config file to our list. */
1049  for (char **iter = _network_host_list.Begin(); iter != _network_host_list.End(); iter++) {
1050  NetworkAddServer(*iter);
1051  }
1052  }
1053 
1054  new NetworkGameWindow(&_network_game_window_desc);
1055 }
1056 
1058  byte widget_id;
1060 
1061  NetworkStartServerWindow(WindowDesc *desc) : Window(desc), name_editbox(NETWORK_NAME_LENGTH)
1062  {
1063  this->InitNested(WN_NETWORK_WINDOW_START);
1064 
1065  this->querystrings[WID_NSS_GAMENAME] = &this->name_editbox;
1066  this->name_editbox.text.Assign(_settings_client.network.server_name);
1067 
1068  this->SetFocusedWidget(WID_NSS_GAMENAME);
1069  }
1070 
1071  virtual void SetStringParameters(int widget) const
1072  {
1073  switch (widget) {
1074  case WID_NSS_CONNTYPE_BTN:
1076  break;
1077 
1078  case WID_NSS_CLIENTS_TXT:
1080  break;
1081 
1082  case WID_NSS_COMPANIES_TXT:
1084  break;
1085 
1088  break;
1089 
1090  case WID_NSS_LANGUAGE_BTN:
1091  SetDParam(0, STR_NETWORK_LANG_ANY + _settings_client.network.server_lang);
1092  break;
1093  }
1094  }
1095 
1096  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1097  {
1098  switch (widget) {
1099  case WID_NSS_CONNTYPE_BTN:
1101  size->width += padding.width;
1102  size->height += padding.height;
1103  break;
1104  }
1105  }
1106 
1107  virtual void DrawWidget(const Rect &r, int widget) const
1108  {
1109  switch (widget) {
1110  case WID_NSS_SETPWD:
1111  /* If password is set, draw red '*' next to 'Set password' button. */
1112  if (!StrEmpty(_settings_client.network.server_password)) DrawString(r.right + WD_FRAMERECT_LEFT, this->width - WD_FRAMERECT_RIGHT, r.top, "*", TC_RED);
1113  }
1114  }
1115 
1116  virtual void OnClick(Point pt, int widget, int click_count)
1117  {
1118  switch (widget) {
1119  case WID_NSS_CANCEL: // Cancel button
1120  ShowNetworkGameWindow();
1121  break;
1122 
1123  case WID_NSS_SETPWD: // Set password button
1124  this->widget_id = WID_NSS_SETPWD;
1126  ShowQueryString(STR_JUST_RAW_STRING, STR_NETWORK_START_SERVER_SET_PASSWORD, 20, this, CS_ALPHANUMERAL, QSF_NONE);
1127  break;
1128 
1129  case WID_NSS_CONNTYPE_BTN: // Connection type
1130  ShowDropDownMenu(this, _connection_types_dropdown, _settings_client.network.server_advertise, WID_NSS_CONNTYPE_BTN, 0, 0); // do it for widget WID_NSS_CONNTYPE_BTN
1131  break;
1132 
1133  case WID_NSS_CLIENTS_BTND: case WID_NSS_CLIENTS_BTNU: // Click on up/down button for number of clients
1134  case WID_NSS_COMPANIES_BTND: case WID_NSS_COMPANIES_BTNU: // Click on up/down button for number of companies
1135  case WID_NSS_SPECTATORS_BTND: case WID_NSS_SPECTATORS_BTNU: // Click on up/down button for number of spectators
1136  /* Don't allow too fast scrolling. */
1137  if (!(this->flags & WF_TIMEOUT) || this->timeout_timer <= 1) {
1138  this->HandleButtonClick(widget);
1139  this->SetDirty();
1140  switch (widget) {
1141  default: NOT_REACHED();
1144  break;
1147  break;
1150  break;
1151  }
1152  }
1153  _left_button_clicked = false;
1154  break;
1155 
1156  case WID_NSS_CLIENTS_TXT: // Click on number of clients
1157  this->widget_id = WID_NSS_CLIENTS_TXT;
1159  ShowQueryString(STR_JUST_INT, STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS, 4, this, CS_NUMERAL, QSF_NONE);
1160  break;
1161 
1162  case WID_NSS_COMPANIES_TXT: // Click on number of companies
1163  this->widget_id = WID_NSS_COMPANIES_TXT;
1165  ShowQueryString(STR_JUST_INT, STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES, 3, this, CS_NUMERAL, QSF_NONE);
1166  break;
1167 
1168  case WID_NSS_SPECTATORS_TXT: // Click on number of spectators
1169  this->widget_id = WID_NSS_SPECTATORS_TXT;
1171  ShowQueryString(STR_JUST_INT, STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS, 4, this, CS_NUMERAL, QSF_NONE);
1172  break;
1173 
1174  case WID_NSS_LANGUAGE_BTN: { // Language
1175  uint sel = 0;
1176  for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
1177  if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _settings_client.network.server_lang) {
1178  sel = i;
1179  break;
1180  }
1181  }
1182  ShowDropDownMenu(this, _language_dropdown, sel, WID_NSS_LANGUAGE_BTN, 0, 0);
1183  break;
1184  }
1185 
1186  case WID_NSS_GENERATE_GAME: // Start game
1187  _is_network_server = true;
1188  if (_ctrl_pressed) {
1190  } else {
1192  }
1193  break;
1194 
1195  case WID_NSS_LOAD_GAME:
1196  _is_network_server = true;
1198  break;
1199 
1200  case WID_NSS_PLAY_SCENARIO:
1201  _is_network_server = true;
1203  break;
1204 
1206  _is_network_server = true;
1208  break;
1209  }
1210  }
1211 
1212  virtual void OnDropdownSelect(int widget, int index)
1213  {
1214  switch (widget) {
1215  case WID_NSS_CONNTYPE_BTN:
1216  _settings_client.network.server_advertise = (index != 0);
1217  break;
1218  case WID_NSS_LANGUAGE_BTN:
1219  _settings_client.network.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
1220  break;
1221  default:
1222  NOT_REACHED();
1223  }
1224 
1225  this->SetDirty();
1226  }
1227 
1228  virtual void OnEditboxChanged(int wid)
1229  {
1230  if (wid == WID_NSS_GAMENAME) {
1232  }
1233  }
1234 
1235  virtual void OnTimeout()
1236  {
1238  for (const int *widget = raise_widgets; *widget != WIDGET_LIST_END; widget++) {
1239  if (this->IsWidgetLowered(*widget)) {
1240  this->RaiseWidget(*widget);
1241  this->SetWidgetDirty(*widget);
1242  }
1243  }
1244  }
1245 
1246  virtual void OnQueryTextFinished(char *str)
1247  {
1248  if (str == NULL) return;
1249 
1250  if (this->widget_id == WID_NSS_SETPWD) {
1252  } else {
1253  int32 value = atoi(str);
1254  this->SetWidgetDirty(this->widget_id);
1255  switch (this->widget_id) {
1256  default: NOT_REACHED();
1260  }
1261  }
1262 
1263  this->SetDirty();
1264  }
1265 };
1266 
1267 static const NWidgetPart _nested_network_start_server_window_widgets[] = {
1269  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1270  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_NETWORK_START_SERVER_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1271  EndContainer(),
1272  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NSS_BACKGROUND),
1273  NWidget(NWID_VERTICAL), SetPIP(10, 6, 10),
1275  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1276  /* Game name widgets */
1277  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_GAMENAME_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NEW_GAME_NAME, STR_NULL),
1278  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),
1279  EndContainer(),
1280  EndContainer(),
1281 
1283  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1284  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_ADVERTISED, STR_NULL),
1285  NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_CONNTYPE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_ADVERTISED_TOOLTIP),
1286  EndContainer(),
1287  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1288  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_LANGUAGE_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN, STR_NULL),
1289  NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NSS_LANGUAGE_BTN), SetFill(1, 0), SetDataTip(STR_BLACK_STRING, STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP),
1290  EndContainer(),
1291  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1292  NWidget(NWID_SPACER), SetFill(1, 1),
1293  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_SETPWD), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_SET_PASSWORD, STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP),
1294  EndContainer(),
1295  EndContainer(),
1296 
1298  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1299  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_CLIENTS_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS, STR_NULL),
1301  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),
1302  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),
1303  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),
1304  EndContainer(),
1305  EndContainer(),
1306 
1307  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1308  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_COMPANIES_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES, STR_NULL),
1310  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),
1311  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),
1312  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),
1313  EndContainer(),
1314  EndContainer(),
1315 
1316  NWidget(NWID_VERTICAL), SetPIP(0, 1, 0),
1317  NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NSS_SPECTATORS_LABEL), SetFill(1, 0), SetDataTip(STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS, STR_NULL),
1319  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),
1320  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),
1321  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),
1322  EndContainer(),
1323  EndContainer(),
1324  EndContainer(),
1325 
1326  /* 'generate game' and 'load game' buttons */
1328  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_GENERATE_GAME), SetDataTip(STR_INTRO_NEW_GAME, STR_INTRO_TOOLTIP_NEW_GAME), SetFill(1, 0),
1329  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_LOAD_GAME), SetDataTip(STR_INTRO_LOAD_GAME, STR_INTRO_TOOLTIP_LOAD_GAME), SetFill(1, 0),
1330  EndContainer(),
1331 
1332  /* 'play scenario' and 'play heightmap' buttons */
1334  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_PLAY_SCENARIO), SetDataTip(STR_INTRO_PLAY_SCENARIO, STR_INTRO_TOOLTIP_PLAY_SCENARIO), SetFill(1, 0),
1335  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_PLAY_HEIGHTMAP), SetDataTip(STR_INTRO_PLAY_HEIGHTMAP, STR_INTRO_TOOLTIP_PLAY_HEIGHTMAP), SetFill(1, 0),
1336  EndContainer(),
1337 
1339  NWidget(NWID_SPACER), SetFill(1, 0),
1340  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NSS_CANCEL), SetDataTip(STR_BUTTON_CANCEL, STR_NULL), SetMinimalSize(128, 12),
1341  NWidget(NWID_SPACER), SetFill(1, 0),
1342  EndContainer(),
1343  EndContainer(),
1344  EndContainer(),
1345 };
1346 
1347 static WindowDesc _network_start_server_window_desc(
1348  WDP_CENTER, NULL, 0, 0,
1350  0,
1351  _nested_network_start_server_window_widgets, lengthof(_nested_network_start_server_window_widgets)
1352 );
1353 
1354 static void ShowNetworkStartServerWindow()
1355 {
1358 
1359  new NetworkStartServerWindow(&_network_start_server_window_desc);
1360 }
1361 
1362 struct NetworkLobbyWindow : public Window {
1365  NetworkCompanyInfo company_info[MAX_COMPANIES];
1366  Scrollbar *vscroll;
1367 
1369  Window(desc), company(INVALID_COMPANY), server(ngl)
1370  {
1371  this->CreateNestedTree();
1372  this->vscroll = this->GetScrollbar(WID_NL_SCROLLBAR);
1373  this->FinishInitNested(WN_NETWORK_WINDOW_LOBBY);
1374  }
1375 
1376  CompanyID NetworkLobbyFindCompanyIndex(byte pos) const
1377  {
1378  /* Scroll through all this->company_info and get the 'pos' item that is not empty. */
1379  for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
1380  if (!StrEmpty(this->company_info[i].company_name)) {
1381  if (pos-- == 0) return i;
1382  }
1383  }
1384 
1385  return COMPANY_FIRST;
1386  }
1387 
1388  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1389  {
1390  switch (widget) {
1391  case WID_NL_HEADER:
1393  break;
1394 
1395  case WID_NL_MATRIX:
1396  resize->height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
1397  size->height = 10 * resize->height;
1398  break;
1399 
1400  case WID_NL_DETAILS:
1401  size->height = 30 + 11 * FONT_HEIGHT_NORMAL;
1402  break;
1403  }
1404  }
1405 
1406  virtual void SetStringParameters(int widget) const
1407  {
1408  switch (widget) {
1409  case WID_NL_TEXT:
1410  SetDParamStr(0, this->server->info.server_name);
1411  break;
1412  }
1413  }
1414 
1415  virtual void DrawWidget(const Rect &r, int widget) const
1416  {
1417  switch (widget) {
1418  case WID_NL_DETAILS:
1419  this->DrawDetails(r);
1420  break;
1421 
1422  case WID_NL_MATRIX:
1423  this->DrawMatrix(r);
1424  break;
1425  }
1426  }
1427 
1428  virtual void OnPaint()
1429  {
1430  const NetworkGameInfo *gi = &this->server->info;
1431 
1432  /* Join button is disabled when no company is selected and for AI companies. */
1433  this->SetWidgetDisabledState(WID_NL_JOIN, this->company == INVALID_COMPANY || GetLobbyCompanyInfo(this->company)->ai);
1434  /* Cannot start new company if there are too many. */
1435  this->SetWidgetDisabledState(WID_NL_NEW, gi->companies_on >= gi->companies_max);
1436  /* Cannot spectate if there are too many spectators. */
1437  this->SetWidgetDisabledState(WID_NL_SPECTATE, gi->spectators_on >= gi->spectators_max);
1438 
1439  this->vscroll->SetCount(gi->companies_on);
1440 
1441  /* Draw window widgets */
1442  this->DrawWidgets();
1443  }
1444 
1445  void DrawMatrix(const Rect &r) const
1446  {
1447  bool rtl = _current_text_dir == TD_RTL;
1448  uint left = r.left + WD_FRAMERECT_LEFT;
1449  uint right = r.right - WD_FRAMERECT_RIGHT;
1450 
1451  Dimension lock_size = GetSpriteSize(SPR_LOCK);
1452  int lock_width = lock_size.width;
1453  int lock_y_offset = (this->resize.step_height - WD_MATRIX_TOP - WD_MATRIX_BOTTOM - lock_size.height) / 2;
1454 
1455  Dimension profit_size = GetSpriteSize(SPR_PROFIT_LOT);
1456  int profit_width = lock_size.width;
1457  int profit_y_offset = (this->resize.step_height - WD_MATRIX_TOP - WD_MATRIX_BOTTOM - profit_size.height) / 2;
1458 
1459  uint text_left = left + (rtl ? lock_width + profit_width + 4 : 0);
1460  uint text_right = right - (rtl ? 0 : lock_width + profit_width + 4);
1461  uint profit_left = rtl ? left : right - profit_width;
1462  uint lock_left = rtl ? left + profit_width + 2 : right - profit_width - lock_width - 2;
1463 
1464  int y = r.top + WD_MATRIX_TOP;
1465  /* Draw company list */
1466  int pos = this->vscroll->GetPosition();
1467  while (pos < this->server->info.companies_on) {
1468  byte company = NetworkLobbyFindCompanyIndex(pos);
1469  bool income = false;
1470  if (this->company == company) {
1471  GfxFillRect(r.left + 1, y - 2, r.right - 1, y + FONT_HEIGHT_NORMAL, PC_GREY); // show highlighted item with a different colour
1472  }
1473 
1474  DrawString(text_left, text_right, y, this->company_info[company].company_name, TC_BLACK);
1475  if (this->company_info[company].use_password != 0) DrawSprite(SPR_LOCK, PAL_NONE, lock_left, y + lock_y_offset);
1476 
1477  /* If the company's income was positive puts a green dot else a red dot */
1478  if (this->company_info[company].income >= 0) income = true;
1479  DrawSprite(income ? SPR_PROFIT_LOT : SPR_PROFIT_NEGATIVE, PAL_NONE, profit_left, y + profit_y_offset);
1480 
1481  pos++;
1482  y += this->resize.step_height;
1483  if (pos >= this->vscroll->GetPosition() + this->vscroll->GetCapacity()) break;
1484  }
1485  }
1486 
1487  void DrawDetails(const Rect &r) const
1488  {
1489  const int detail_height = 12 + FONT_HEIGHT_NORMAL + 12;
1490  /* Draw info about selected company when it is selected in the left window. */
1491  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + detail_height - 1, PC_DARK_BLUE);
1492  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);
1493 
1494  if (this->company == INVALID_COMPANY || StrEmpty(this->company_info[this->company].company_name)) return;
1495 
1496  int y = r.top + detail_height + 4;
1497  const NetworkGameInfo *gi = &this->server->info;
1498 
1499  SetDParam(0, gi->clients_on);
1500  SetDParam(1, gi->clients_max);
1501  SetDParam(2, gi->companies_on);
1502  SetDParam(3, gi->companies_max);
1503  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_SERVER_LIST_CLIENTS);
1504  y += FONT_HEIGHT_NORMAL;
1505 
1506  SetDParamStr(0, this->company_info[this->company].company_name);
1507  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_COMPANY_NAME);
1508  y += FONT_HEIGHT_NORMAL;
1509 
1510  SetDParam(0, this->company_info[this->company].inaugurated_year);
1511  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR); // inauguration year
1512  y += FONT_HEIGHT_NORMAL;
1513 
1514  SetDParam(0, this->company_info[this->company].company_value);
1515  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_VALUE); // company value
1516  y += FONT_HEIGHT_NORMAL;
1517 
1518  SetDParam(0, this->company_info[this->company].money);
1519  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_CURRENT_BALANCE); // current balance
1520  y += FONT_HEIGHT_NORMAL;
1521 
1522  SetDParam(0, this->company_info[this->company].income);
1523  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_LAST_YEARS_INCOME); // last year's income
1524  y += FONT_HEIGHT_NORMAL;
1525 
1526  SetDParam(0, this->company_info[this->company].performance);
1527  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_PERFORMANCE); // performance
1528  y += FONT_HEIGHT_NORMAL;
1529 
1530  SetDParam(0, this->company_info[this->company].num_vehicle[NETWORK_VEH_TRAIN]);
1531  SetDParam(1, this->company_info[this->company].num_vehicle[NETWORK_VEH_LORRY]);
1532  SetDParam(2, this->company_info[this->company].num_vehicle[NETWORK_VEH_BUS]);
1533  SetDParam(3, this->company_info[this->company].num_vehicle[NETWORK_VEH_SHIP]);
1534  SetDParam(4, this->company_info[this->company].num_vehicle[NETWORK_VEH_PLANE]);
1535  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_VEHICLES); // vehicles
1536  y += FONT_HEIGHT_NORMAL;
1537 
1538  SetDParam(0, this->company_info[this->company].num_station[NETWORK_VEH_TRAIN]);
1539  SetDParam(1, this->company_info[this->company].num_station[NETWORK_VEH_LORRY]);
1540  SetDParam(2, this->company_info[this->company].num_station[NETWORK_VEH_BUS]);
1541  SetDParam(3, this->company_info[this->company].num_station[NETWORK_VEH_SHIP]);
1542  SetDParam(4, this->company_info[this->company].num_station[NETWORK_VEH_PLANE]);
1543  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_STATIONS); // stations
1544  y += FONT_HEIGHT_NORMAL;
1545 
1546  SetDParamStr(0, this->company_info[this->company].clients);
1547  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_NETWORK_GAME_LOBBY_PLAYERS); // players
1548  }
1549 
1550  virtual void OnClick(Point pt, int widget, int click_count)
1551  {
1552  switch (widget) {
1553  case WID_NL_CANCEL: // Cancel button
1554  ShowNetworkGameWindow();
1555  break;
1556 
1557  case WID_NL_MATRIX: { // Company list
1558  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NL_MATRIX);
1559  this->company = (id_v >= this->server->info.companies_on) ? INVALID_COMPANY : NetworkLobbyFindCompanyIndex(id_v);
1560  this->SetDirty();
1561 
1562  /* FIXME the disabling should go into some InvalidateData, which is called instead of the SetDirty */
1563  if (click_count > 1 && !this->IsWidgetDisabled(WID_NL_JOIN)) this->OnClick(pt, WID_NL_JOIN, 1);
1564  break;
1565  }
1566 
1567  case WID_NL_JOIN: // Join company
1568  /* Button can be clicked only when it is enabled. */
1569  NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), this->company);
1570  break;
1571 
1572  case WID_NL_NEW: // New company
1574  break;
1575 
1576  case WID_NL_SPECTATE: // Spectate game
1578  break;
1579 
1580  case WID_NL_REFRESH: // Refresh
1581  NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
1583  /* Clear the information so removed companies don't remain */
1584  memset(this->company_info, 0, sizeof(this->company_info));
1585  break;
1586  }
1587  }
1588 
1589  virtual void OnResize()
1590  {
1591  this->vscroll->SetCapacityFromWidget(this, WID_NL_MATRIX);
1592  }
1593 };
1594 
1595 static const NWidgetPart _nested_network_lobby_window_widgets[] = {
1597  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1598  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_NETWORK_GAME_LOBBY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1599  EndContainer(),
1600  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NL_BACKGROUND),
1601  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),
1603  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 10),
1604  /* Company list. */
1606  NWidget(WWT_PANEL, COLOUR_WHITE, WID_NL_HEADER), SetMinimalSize(146, 0), SetResize(1, 0), SetFill(1, 0), EndContainer(),
1607  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),
1608  EndContainer(),
1609  NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NL_SCROLLBAR),
1611  /* Company info. */
1612  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NL_DETAILS), SetMinimalSize(232, 0), SetResize(1, 1), SetFill(1, 1), EndContainer(),
1613  EndContainer(),
1615  /* Buttons. */
1618  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),
1619  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),
1620  EndContainer(),
1622  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),
1623  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),
1624  EndContainer(),
1626  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NL_CANCEL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
1627  NWidget(NWID_SPACER), SetFill(1, 1),
1628  EndContainer(),
1629  EndContainer(),
1631  EndContainer(),
1632 };
1633 
1634 static WindowDesc _network_lobby_window_desc(
1635  WDP_CENTER, NULL, 0, 0,
1637  0,
1638  _nested_network_lobby_window_widgets, lengthof(_nested_network_lobby_window_widgets)
1639 );
1640 
1646 {
1649 
1650  NetworkTCPQueryServer(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); // company info
1652 
1653  new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
1654 }
1655 
1662 {
1664  return (lobby != NULL && company < MAX_COMPANIES) ? &lobby->company_info[company] : NULL;
1665 }
1666 
1667 /* The window below gives information about the connected clients
1668  * and also makes able to give money to them, kick them (if server)
1669  * and stuff like that. */
1670 
1671 extern void DrawCompanyIcon(CompanyID cid, int x, int y);
1672 
1678 
1679 static const NWidgetPart _nested_client_list_popup_widgets[] = {
1680  NWidget(WWT_PANEL, COLOUR_GREY, WID_CLP_PANEL), EndContainer(),
1681 };
1682 
1683 static WindowDesc _client_list_popup_desc(
1684  WDP_AUTO, NULL, 0, 0,
1686  0,
1687  _nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets)
1688 );
1689 
1690 /* Here we start to define the options out of the menu */
1691 static void ClientList_Kick(const NetworkClientInfo *ci)
1692 {
1694 }
1695 
1696 static void ClientList_Ban(const NetworkClientInfo *ci)
1697 {
1699 }
1700 
1701 static void ClientList_GiveMoney(const NetworkClientInfo *ci)
1702 {
1703  ShowNetworkGiveMoneyWindow(ci->client_playas);
1704 }
1705 
1706 static void ClientList_SpeakToClient(const NetworkClientInfo *ci)
1707 {
1709 }
1710 
1711 static void ClientList_SpeakToCompany(const NetworkClientInfo *ci)
1712 {
1714 }
1715 
1716 static void ClientList_SpeakToAll(const NetworkClientInfo *ci)
1717 {
1719 }
1720 
1727  };
1728 
1729  uint sel_index;
1730  ClientID client_id;
1731  Point desired_location;
1733 
1739  inline void AddAction(StringID name, ClientList_Action_Proc *proc)
1740  {
1741  ClientListAction *action = this->actions.Append();
1742  action->name = name;
1743  action->proc = proc;
1744  }
1745 
1746  NetworkClientListPopupWindow(WindowDesc *desc, int x, int y, ClientID client_id) :
1747  Window(desc),
1748  sel_index(0), client_id(client_id)
1749  {
1750  this->desired_location.x = x;
1751  this->desired_location.y = y;
1752 
1753  const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id);
1754 
1755  if (_network_own_client_id != ci->client_id) {
1756  this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, &ClientList_SpeakToClient);
1757  }
1758 
1760  this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, &ClientList_SpeakToCompany);
1761  }
1762  this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, &ClientList_SpeakToAll);
1763 
1764  if (_network_own_client_id != ci->client_id) {
1765  /* We are no spectator and the company we want to give money to is no spectator and money gifts are allowed. */
1767  this->AddAction(STR_NETWORK_CLIENTLIST_GIVE_MONEY, &ClientList_GiveMoney);
1768  }
1769  }
1770 
1771  /* A server can kick clients (but not himself). */
1773  this->AddAction(STR_NETWORK_CLIENTLIST_KICK, &ClientList_Kick);
1774  this->AddAction(STR_NETWORK_CLIENTLIST_BAN, &ClientList_Ban);
1775  }
1776 
1777  this->InitNested(client_id);
1778  CLRBITS(this->flags, WF_WHITE_BORDER);
1779  }
1780 
1781  virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
1782  {
1783  return this->desired_location;
1784  }
1785 
1786  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1787  {
1788  Dimension d = *size;
1789  for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++) {
1790  d = maxdim(GetStringBoundingBox(action->name), d);
1791  }
1792 
1793  d.height *= this->actions.Length();
1795  d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1796  *size = d;
1797  }
1798 
1799  virtual void DrawWidget(const Rect &r, int widget) const
1800  {
1801  /* Draw the actions */
1802  int sel = this->sel_index;
1803  int y = r.top + WD_FRAMERECT_TOP;
1804  for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++, y += FONT_HEIGHT_NORMAL) {
1805  TextColour colour;
1806  if (sel-- == 0) { // Selected item, highlight it
1807  GfxFillRect(r.left + 1, y, r.right - 1, y + FONT_HEIGHT_NORMAL - 1, PC_BLACK);
1808  colour = TC_WHITE;
1809  } else {
1810  colour = TC_BLACK;
1811  }
1812 
1813  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, action->name, colour);
1814  }
1815  }
1816 
1817  virtual void OnMouseLoop()
1818  {
1819  /* We selected an action */
1820  uint index = (_cursor.pos.y - this->top - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL;
1821 
1822  if (_left_button_down) {
1823  if (index == this->sel_index || index >= this->actions.Length()) return;
1824 
1825  this->sel_index = index;
1826  this->SetDirty();
1827  } else {
1828  if (index < this->actions.Length() && _cursor.pos.y >= this->top) {
1829  const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(this->client_id);
1830  if (ci != NULL) this->actions[index].proc(ci);
1831  }
1832 
1834  }
1835  }
1836 };
1837 
1841 static void PopupClientList(ClientID client_id, int x, int y)
1842 {
1844 
1845  if (NetworkClientInfo::GetByClientID(client_id) == NULL) return;
1846 
1847  new NetworkClientListPopupWindow(&_client_list_popup_desc, x, y, client_id);
1848 }
1849 
1850 static const NWidgetPart _nested_client_list_widgets[] = {
1852  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1853  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_COMPANY_LIST_CLIENT_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1854  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1855  EndContainer(),
1857 };
1858 
1859 static WindowDesc _client_list_desc(
1860  WDP_AUTO, "list_clients", 0, 0,
1862  0,
1863  _nested_client_list_widgets, lengthof(_nested_client_list_widgets)
1864 );
1865 
1870  int selected_item;
1871 
1872  uint server_client_width;
1873  uint line_height;
1874 
1875  Dimension icon_size;
1876 
1877  NetworkClientListWindow(WindowDesc *desc, WindowNumber window_number) :
1878  Window(desc),
1879  selected_item(-1)
1880  {
1881  this->InitNested(window_number);
1882  }
1883 
1888  {
1889  int num = 0;
1890  const NetworkClientInfo *ci;
1891 
1892  /* Should be replaced with a loop through all clients */
1893  FOR_ALL_CLIENT_INFOS(ci) {
1894  if (ci->client_playas != COMPANY_INACTIVE_CLIENT) num++;
1895  }
1896 
1897  num *= this->line_height;
1898 
1899  int diff = (num + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM) - (this->GetWidget<NWidgetBase>(WID_CL_PANEL)->current_y);
1900  /* If height is changed */
1901  if (diff != 0) {
1902  ResizeWindow(this, 0, diff, false);
1903  return false;
1904  }
1905  return true;
1906  }
1907 
1908  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1909  {
1910  if (widget != WID_CL_PANEL) return;
1911 
1912  this->server_client_width = max(GetStringBoundingBox(STR_NETWORK_SERVER).width, GetStringBoundingBox(STR_NETWORK_CLIENT).width) + WD_FRAMERECT_RIGHT;
1913  this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
1914  this->line_height = max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
1915 
1916  uint width = 100; // Default width
1917  const NetworkClientInfo *ci;
1918  FOR_ALL_CLIENT_INFOS(ci) {
1919  width = max(width, GetStringBoundingBox(ci->client_name).width);
1920  }
1921 
1922  size->width = WD_FRAMERECT_LEFT + this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT + width + WD_FRAMERECT_RIGHT;
1923  }
1924 
1925  virtual void OnPaint()
1926  {
1927  /* Check if we need to reset the height */
1928  if (!this->CheckClientListHeight()) return;
1929 
1930  this->DrawWidgets();
1931  }
1932 
1933  virtual void DrawWidget(const Rect &r, int widget) const
1934  {
1935  if (widget != WID_CL_PANEL) return;
1936 
1937  bool rtl = _current_text_dir == TD_RTL;
1938  int icon_offset = (this->line_height - icon_size.height) / 2;
1939  int text_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
1940 
1941  uint y = r.top + WD_FRAMERECT_TOP;
1942  uint left = r.left + WD_FRAMERECT_LEFT;
1943  uint right = r.right - WD_FRAMERECT_RIGHT;
1944  uint type_icon_width = this->server_client_width + this->icon_size.width + WD_FRAMERECT_LEFT;
1945 
1946 
1947  uint type_left = rtl ? right - this->server_client_width : left;
1948  uint type_right = rtl ? right : left + this->server_client_width - 1;
1949  uint icon_left = rtl ? right - type_icon_width + WD_FRAMERECT_LEFT : left + this->server_client_width;
1950  uint name_left = rtl ? left : left + type_icon_width;
1951  uint name_right = rtl ? right - type_icon_width : right;
1952 
1953  int i = 0;
1954  const NetworkClientInfo *ci;
1955  FOR_ALL_CLIENT_INFOS(ci) {
1956  TextColour colour;
1957  if (this->selected_item == i++) { // Selected item, highlight it
1958  GfxFillRect(r.left + 1, y, r.right - 1, y + this->line_height - 1, PC_BLACK);
1959  colour = TC_WHITE;
1960  } else {
1961  colour = TC_BLACK;
1962  }
1963 
1964  if (ci->client_id == CLIENT_ID_SERVER) {
1965  DrawString(type_left, type_right, y + text_offset, STR_NETWORK_SERVER, colour);
1966  } else {
1967  DrawString(type_left, type_right, y + text_offset, STR_NETWORK_CLIENT, colour);
1968  }
1969 
1970  /* Filter out spectators */
1971  if (Company::IsValidID(ci->client_playas)) DrawCompanyIcon(ci->client_playas, icon_left, y + icon_offset);
1972 
1973  DrawString(name_left, name_right, y + text_offset, ci->client_name, colour);
1974 
1975  y += line_height;
1976  }
1977  }
1978 
1979  virtual void OnClick(Point pt, int widget, int click_count)
1980  {
1981  /* Show the popup with option */
1982  if (this->selected_item != -1) {
1983  NetworkClientInfo *ci;
1984 
1985  int client_no = this->selected_item;
1986  FOR_ALL_CLIENT_INFOS(ci) {
1987  if (client_no == 0) break;
1988  client_no--;
1989  }
1990 
1991  if (ci != NULL) PopupClientList(ci->client_id, pt.x + this->left, pt.y + this->top);
1992  }
1993  }
1994 
1995  virtual void OnMouseOver(Point pt, int widget)
1996  {
1997  /* -1 means we left the current window */
1998  if (pt.y == -1) {
1999  this->selected_item = -1;
2000  this->SetDirty();
2001  return;
2002  }
2003 
2004  /* Find the new selected item (if any) */
2005  pt.y -= this->GetWidget<NWidgetBase>(WID_CL_PANEL)->pos_y;
2006  int item = -1;
2008  item = (pt.y - WD_FRAMERECT_TOP) / this->line_height;
2009  }
2010 
2011  /* It did not change.. no update! */
2012  if (item == this->selected_item) return;
2013  this->selected_item = item;
2014 
2015  /* Repaint */
2016  this->SetDirty();
2017  }
2018 };
2019 
2020 void ShowClientList()
2021 {
2022  AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0);
2023 }
2024 
2029 
2031  NetworkPasswordType password_type;
2032 
2034  {
2036  this->InitNested(WN_NETWORK_STATUS_WINDOW_JOIN);
2037  }
2038 
2039  virtual void DrawWidget(const Rect &r, int widget) const
2040  {
2041  if (widget != WID_NJS_BACKGROUND) return;
2042 
2043  uint8 progress; // used for progress bar
2044  DrawString(r.left + 2, r.right - 2, r.top + 20, STR_NETWORK_CONNECTING_1 + _network_join_status, TC_FROMSTRING, SA_HOR_CENTER);
2045  switch (_network_join_status) {
2046  case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
2047  case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
2048  progress = 10; // first two stages 10%
2049  break;
2050  case NETWORK_JOIN_STATUS_WAITING:
2051  SetDParam(0, _network_join_waiting);
2052  DrawString(r.left + 2, r.right - 2, r.top + 20 + FONT_HEIGHT_NORMAL, STR_NETWORK_CONNECTING_WAITING, TC_FROMSTRING, SA_HOR_CENTER);
2053  progress = 15; // third stage is 15%
2054  break;
2055  case NETWORK_JOIN_STATUS_DOWNLOADING:
2056  SetDParam(0, _network_join_bytes);
2057  SetDParam(1, _network_join_bytes_total);
2058  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);
2059  if (_network_join_bytes_total == 0) {
2060  progress = 15; // We don't have the final size yet; the server is still compressing!
2061  break;
2062  }
2063  FALLTHROUGH;
2064 
2065  default: // Waiting is 15%, so the resting receivement of map is maximum 70%
2066  progress = 15 + _network_join_bytes * (100 - 15) / _network_join_bytes_total;
2067  }
2068 
2069  /* Draw nice progress bar :) */
2070  DrawFrameRect(r.left + 20, r.top + 5, (int)((this->width - 20) * progress / 100), r.top + 15, COLOUR_MAUVE, FR_NONE);
2071  }
2072 
2073  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2074  {
2075  if (widget != WID_NJS_BACKGROUND) return;
2076 
2077  size->height = 25 + 2 * FONT_HEIGHT_NORMAL;
2078 
2079  /* Account for the statuses */
2080  uint width = 0;
2081  for (uint i = 0; i < NETWORK_JOIN_STATUS_END; i++) {
2082  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_1 + i).width);
2083  }
2084 
2085  /* For the number of waiting (other) players */
2087  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_WAITING).width);
2088 
2089  /* Account for downloading ~ 10 MiB */
2090  SetDParamMaxDigits(0, 8);
2091  SetDParamMaxDigits(1, 8);
2092  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_DOWNLOADING_1).width);
2093  width = max(width, GetStringBoundingBox(STR_NETWORK_CONNECTING_DOWNLOADING_2).width);
2094 
2095  /* Give a bit more clearing for the widest strings than strictly needed */
2096  size->width = width + WD_FRAMERECT_LEFT + WD_FRAMERECT_BOTTOM + 10;
2097  }
2098 
2099  virtual void OnClick(Point pt, int widget, int click_count)
2100  {
2101  if (widget == WID_NJS_CANCELOK) { // Disconnect button
2103  SwitchToMode(SM_MENU);
2104  ShowNetworkGameWindow();
2105  }
2106  }
2107 
2108  virtual void OnQueryTextFinished(char *str)
2109  {
2110  if (StrEmpty(str)) {
2112  ShowNetworkGameWindow();
2113  return;
2114  }
2115 
2116  switch (this->password_type) {
2119  default: NOT_REACHED();
2120  }
2121  }
2122 };
2123 
2124 static const NWidgetPart _nested_network_join_status_window_widgets[] = {
2125  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_NETWORK_CONNECTING_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2126  NWidget(WWT_PANEL, COLOUR_GREY),
2127  NWidget(WWT_EMPTY, COLOUR_GREY, WID_NJS_BACKGROUND),
2129  NWidget(NWID_SPACER), SetMinimalSize(75, 0), SetFill(1, 0),
2130  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NJS_CANCELOK), SetMinimalSize(101, 12), SetDataTip(STR_NETWORK_CONNECTION_DISCONNECT, STR_NULL),
2131  NWidget(NWID_SPACER), SetMinimalSize(75, 0), SetFill(1, 0),
2132  EndContainer(),
2134  EndContainer(),
2135 };
2136 
2137 static WindowDesc _network_join_status_window_desc(
2138  WDP_CENTER, NULL, 0, 0,
2140  WDF_MODAL,
2141  _nested_network_join_status_window_widgets, lengthof(_nested_network_join_status_window_widgets)
2142 );
2143 
2144 void ShowJoinStatusWindow()
2145 {
2147  new NetworkJoinStatusWindow(&_network_join_status_window_desc);
2148 }
2149 
2150 void ShowNetworkNeedPassword(NetworkPasswordType npt)
2151 {
2153  if (w == NULL) return;
2154  w->password_type = npt;
2155 
2156  StringID caption;
2157  switch (npt) {
2158  default: NOT_REACHED();
2159  case NETWORK_GAME_PASSWORD: caption = STR_NETWORK_NEED_GAME_PASSWORD_CAPTION; break;
2160  case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break;
2161  }
2162  ShowQueryString(STR_EMPTY, caption, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_NONE);
2163 }
2164 
2167 
2168  NetworkCompanyPasswordWindow(WindowDesc *desc, Window *parent) : Window(desc), password_editbox(lengthof(_settings_client.network.default_company_pass))
2169  {
2170  this->InitNested(0);
2171 
2172  this->parent = parent;
2173  this->querystrings[WID_NCP_PASSWORD] = &this->password_editbox;
2174  this->password_editbox.cancel_button = WID_NCP_CANCEL;
2175  this->password_editbox.ok_button = WID_NCP_OK;
2176  this->SetFocusedWidget(WID_NCP_PASSWORD);
2177  }
2178 
2179  void OnOk()
2180  {
2181  if (this->IsWidgetLowered(WID_NCP_SAVE_AS_DEFAULT_PASSWORD)) {
2183  }
2184 
2185  NetworkChangeCompanyPassword(_local_company, this->password_editbox.text.buf);
2186  }
2187 
2188  virtual void OnClick(Point pt, int widget, int click_count)
2189  {
2190  switch (widget) {
2191  case WID_NCP_OK:
2192  this->OnOk();
2193  FALLTHROUGH;
2194 
2195  case WID_NCP_CANCEL:
2196  delete this;
2197  break;
2198 
2200  this->ToggleWidgetLoweredState(WID_NCP_SAVE_AS_DEFAULT_PASSWORD);
2201  this->SetDirty();
2202  break;
2203  }
2204  }
2205 };
2206 
2207 static const NWidgetPart _nested_network_company_password_window_widgets[] = {
2209  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2210  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_COMPANY_PASSWORD_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2211  EndContainer(),
2212  NWidget(WWT_PANEL, COLOUR_GREY, WID_NCP_BACKGROUND),
2213  NWidget(NWID_VERTICAL), SetPIP(5, 5, 5),
2214  NWidget(NWID_HORIZONTAL), SetPIP(5, 5, 5),
2215  NWidget(WWT_TEXT, COLOUR_GREY, WID_NCP_LABEL), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_NULL),
2216  NWidget(WWT_EDITBOX, COLOUR_GREY, WID_NCP_PASSWORD), SetFill(1, 0), SetMinimalSize(194, 12), SetDataTip(STR_COMPANY_VIEW_SET_PASSWORD, STR_NULL),
2217  EndContainer(),
2218  NWidget(NWID_HORIZONTAL), SetPIP(5, 0, 5),
2219  NWidget(NWID_SPACER), SetFill(1, 0),
2221  SetDataTip(STR_COMPANY_PASSWORD_MAKE_DEFAULT, STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP),
2222  EndContainer(),
2223  EndContainer(),
2224  EndContainer(),
2226  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NCP_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_COMPANY_PASSWORD_CANCEL),
2227  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NCP_OK), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_COMPANY_PASSWORD_OK),
2228  EndContainer(),
2229 };
2230 
2231 static WindowDesc _network_company_password_window_desc(
2232  WDP_AUTO, NULL, 0, 0,
2234  0,
2235  _nested_network_company_password_window_widgets, lengthof(_nested_network_company_password_window_widgets)
2236 );
2237 
2238 void ShowNetworkCompanyPasswordWindow(Window *parent)
2239 {
2241 
2242  new NetworkCompanyPasswordWindow(&_network_company_password_window_desc, parent);
2243 }
2244 
2245 #endif /* ENABLE_NETWORK */
EventState
State of handling an event.
Definition: window_type.h:713
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:113
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
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:409
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:1114
void ResetState()
Reset the matching state to process a new item.
The passed event is not handled.
Definition: window_type.h:715
bool Elapsed(uint delta)
Test if a timer has elapsed.
Definition: guitimer_func.h:57
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:1064
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)
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:85
static const uint MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER
Minimum width before adding a new header.
Definition: network_gui.cpp:96
static const uint32 GENERATE_NEW_SEED
Create a new random seed.
Definition: genworld.h:25
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:278
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.
void StartNewGameWithoutGUI(uint32 seed)
Start a normal game without the GUI.
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:282
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:332
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.
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.
static const uint MILLISECONDS_PER_TICK
The number of milliseconds per game tick.
Definition: gfx_type.h:306
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:52
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:124
#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
virtual void OnRealtimeTick(uint delta_ms)
Called periodically.
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:500
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:97
&#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:1159
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:398
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
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:1146
static const StringID _lan_internet_types_dropdown[]
Advertisement options in the server list.
Definition: network_gui.cpp:61
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:580
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.
GUITimer requery_timer
Timer for network requery.
void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop)
Launch save/load dialog in the given mode.
Definition: fios_gui.cpp:896
&#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:108
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:769
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:95
NetworkGameList * server
selected server
static const uint MAX_MAP_SIZE
Maximal map size = 4096.
Definition: map_type.h:68
int32 WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:707
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:714
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:2126
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:834
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:289
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:3301
(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