OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4Network2Dialogs.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2004-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // dialogs for network information
17 
18 #include "C4Include.h"
20 
21 #include "network/C4Network2.h"
23 #include "game/C4Viewport.h"
24 #include "gui/C4GameOptions.h"
25 #include "game/C4Game.h"
26 #include "player/C4PlayerList.h"
27 #include "control/C4GameControl.h"
29 #include "graphics/C4Draw.h"
30 #include "graphics/C4Draw.h"
31 #include "gui/C4Startup.h"
32 #include "lib/StdColors.h"
33 
34 #ifndef HAVE_WINSOCK
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #endif
39 
40 // --------------------------------------------------
41 // C4Network2ClientDlg
42 
44  : C4GUI::InfoDialog(LoadResStr("IDS_NET_CLIENT_INFO"), 10), iClientID(iForClientID)
45 {
46  // initial text update
47  UpdateText();
48 }
49 
51 {
52  // begin updating (clears previous text)
54  // get core
55  const C4Client *pClient = Game.Clients.getClientByID(iClientID);
56  if (!pClient)
57  {
58  // client ID unknown
59  AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_UNKNOWNID"), iClientID);
60  }
61  else
62  {
63  // get client (may be nullptr for local info)
64  C4Network2Client *pNetClient = pClient->getNetClient();
65  // show some info
66  StdCopyStrBuf strInfo;
67  if (!pClient->isActivated()) { strInfo.Append(LoadResStr("IDS_MSG_INACTIVE")); strInfo.Append(" "); }
68  if (pClient->isLocal()) { strInfo.Append(LoadResStr("IDS_MSG_LOCAL")); strInfo.Append(" "); }
69  strInfo.AppendFormat("%s %s (ID #%d)%s",
70  LoadResStr(pClient->isHost() ? "IDS_MSG_HOST" : "IDS_MSG_CLIENT"),
71  pClient->getName(),
72  iClientID,
73  ::Network.isHost() && pNetClient && !pNetClient->isReady() ? " (!ack)" : "");
74  AddLine(strInfo.getData());
75  // show addresses
76  int iCnt;
77  if ((iCnt=pNetClient->getAddrCnt()))
78  {
79  AddLine(LoadResStr("IDS_NET_CLIENT_INFO_ADDRESSES"));
80  for (int i=0; i<iCnt; ++i)
81  {
82  C4Network2Address addr = pNetClient->getAddr(i);
83  AddLineFmt(" %d: %s",
84  i, // adress index
85  addr.toString().getData());
86  }
87  }
88  else
89  AddLine(LoadResStr("IDS_NET_CLIENT_INFO_NOADDRESSES"));
90  // show connection
91  if (pNetClient)
92  {
93  // connections
94  if (pNetClient->isConnected())
95  {
96  AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNECTIONS"),
97  pNetClient->getMsgConn() == pNetClient->getDataConn() ? "Msg/Data" : "Msg",
99  pNetClient->getMsgConn()->getPeerAddr().ToString().getData(),
100  pNetClient->getMsgConn()->getPingTime());
101  if (pNetClient->getMsgConn() != pNetClient->getDataConn())
102  AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNDATA"),
104  pNetClient->getDataConn()->getPeerAddr().ToString().getData(),
105  pNetClient->getDataConn()->getPingTime());
106  }
107  else
108  AddLine(LoadResStr("IDS_NET_CLIENT_INFO_NOCONNECTIONS"));
109  }
110  }
111  // update done
112  EndUpdateText();
113 }
114 
115 
116 // --------------------------------------------------
117 // C4Network2ClientListBox::ClientListItem
118 
119 C4Network2ClientListBox::ClientListItem::ClientListItem(class C4Network2ClientListBox *pForDlg, int iClientID) // ctor
120  : ListItem(pForDlg, iClientID), pStatusIcon(nullptr), pName(nullptr), pPing(nullptr), pActivateBtn(nullptr), pKickBtn(nullptr), last_sound_time(0)
121 {
122  // get associated client
123  const C4Client *pClient = GetClient();
124  // get size
125  int iIconSize = ::GraphicsResource.TextFont.GetLineHeight();
126  if (pForDlg->IsStartup()) iIconSize *= 2;
127  int iWidth = pForDlg->GetItemWidth();
128  int iVerticalIndent = 2;
129  SetBounds(C4Rect(0, 0, iWidth, iIconSize+2*iVerticalIndent));
130  C4GUI::ComponentAligner ca(GetContainedClientRect(), 0,iVerticalIndent);
131  // create subcomponents
132  bool fIsHost = pClient && pClient->isHost();
133  pStatusIcon = new C4GUI::Icon(ca.GetFromLeft(iIconSize), fIsHost ? C4GUI::Ico_Host : C4GUI::Ico_Client);
134  StdStrBuf sNameLabel;
135  if (pClient)
136  {
137  if (pForDlg->IsStartup())
138  sNameLabel.Ref(pClient->getName());
139  else
140  sNameLabel.Format("%s:%s", pClient->getName(), pClient->getNick());
141  }
142  else
143  {
144  sNameLabel.Ref("???");
145  }
146  pName = new C4GUI::Label(sNameLabel.getData(), iIconSize + IconLabelSpacing,iVerticalIndent, ALeft);
147  int iPingRightPos = GetBounds().Wdt - IconLabelSpacing;
148  if (::Network.isHost()) iPingRightPos -= 48;
149  if (::Network.isHost() && pClient && !pClient->isHost())
150  {
151  // activate/deactivate and kick btns for clients at host
152  if (!pForDlg->IsStartup())
153  {
154  pActivateBtn = new C4GUI::CallbackButtonEx<C4Network2ClientListBox::ClientListItem, C4GUI::IconButton>(C4GUI::Ico_Active, GetToprightCornerRect(std::max(iIconSize, 16),std::max(iIconSize, 16),2,1,1), 0, this, &ClientListItem::OnButtonActivate);
155  fShownActive = true;
156  }
157  pKickBtn = new C4GUI::CallbackButtonEx<C4Network2ClientListBox::ClientListItem, C4GUI::IconButton>(C4GUI::Ico_Kick, GetToprightCornerRect(std::max(iIconSize, 16),std::max(iIconSize, 16),2,1,0), 0, this, &ClientListItem::OnButtonKick);
158  pKickBtn->SetToolTip(LoadResStrNoAmp("IDS_NET_KICKCLIENT"));
159  }
160  if (!pForDlg->IsStartup()) if (pClient && !pClient->isLocal())
161  {
162  // wait time
163  pPing = new C4GUI::Label("???", iPingRightPos, iVerticalIndent, ARight);
164  pPing->SetToolTip(LoadResStr("IDS_DESC_CONTROLWAITTIME"));
165  }
166  // add components
167  AddElement(pStatusIcon); AddElement(pName);
168  if (pPing) AddElement(pPing);
169  if (pActivateBtn) AddElement(pActivateBtn);
170  if (pKickBtn) AddElement(pKickBtn);
171  // add to listbox (will eventually get moved)
172  pForDlg->AddElement(this);
173  // first-time update
174  Update();
175 }
176 
177 void C4Network2ClientListBox::ClientListItem::Update()
178 {
179  // update wait label
180  if (pPing)
181  {
182  int iWait = ::Control.Network.ClientPerfStat(iClientID);
183  pPing->SetText(FormatString("%d ms", iWait).getData());
184  pPing->SetColor(C4RGB(
185  Clamp(255-Abs(iWait)*5, 0, 255),
186  Clamp(255-iWait*5, 0, 255),
187  Clamp(255+iWait*5, 0, 255)));
188  }
189  // update activation status
190  const C4Client *pClient = GetClient(); if (!pClient) return;
191  bool fIsActive = pClient->isActivated();
192  if (fIsActive != fShownActive)
193  {
194  fShownActive = fIsActive;
195  if (!pClient->isHost()) pStatusIcon->SetIcon(fIsActive ? C4GUI::Ico_Client : C4GUI::Ico_ObserverClient);
196  if (pActivateBtn)
197  {
198  pActivateBtn->SetIcon(fIsActive ? C4GUI::Ico_Active : C4GUI::Ico_Inactive);
199  pActivateBtn->SetToolTip(LoadResStrNoAmp(fIsActive ? "IDS_NET_DEACTIVATECLIENT" : "IDS_NET_ACTIVATECLIENT"));
200  }
201  }
202  // update players in tooltip
203  StdStrBuf sCltPlrs(Game.PlayerInfos.GetActivePlayerNames(false, iClientID));
204  pName->SetToolTip(sCltPlrs.getData());
205  // update icon: Network status
207  C4Network2Client *pClt = pClient->getNetClient();
208  if (pClt)
209  {
210  switch (pClt->getStatus())
211  {
212  case NCS_Joining: // waiting for join data
213  case NCS_Chasing: // client is behind (status not acknowledged, isn't waited for)
214  case NCS_NotReady: // client is behind (status not acknowledged)
215  icoStatus = C4GUI::Ico_Loading;
216  break;
217 
218  case NCS_Ready: // client acknowledged network status
219  icoStatus = C4GUI::Ico_Ready;
220  break;
221 
222  case NCS_Remove: // client is to be removed
223  icoStatus = C4GUI::Ico_Kick;
224  break;
225 
226  default: // whatever
227  assert(false);
228  icoStatus = C4GUI::Ico_Loading;
229  break;
230  }
231  }
232  // sound icon?
233  if (last_sound_time)
234  {
235  time_t dt = time(nullptr) - last_sound_time;
236  if (dt >= SoundIconShowTime)
237  {
238  // stop showing sound icon
239  last_sound_time = 0;
240  }
241  else
242  {
243  // time not up yet: show sound icon
244  icoStatus = C4GUI::Ico_Sound;
245  }
246  }
247  // network OK - control ready?
248  if (!pForDlg->IsStartup() && (icoStatus == C4GUI::Ico_Ready))
249  {
250  if (!::Control.Network.ClientReady(iClientID, ::Control.ControlTick))
251  {
252  // control not ready
253  icoStatus = C4GUI::Ico_NetWait;
254  }
255  }
256  // set new icon
257  pStatusIcon->SetIcon(icoStatus);
258 }
259 
260 const C4Client *C4Network2ClientListBox::ClientListItem::GetClient() const
261 {
262  return Game.Clients.getClientByID(iClientID);
263 }
264 
265 C4Network2ClientListBox::ClientListItem *C4Network2ClientListBox::GetClientListItem(int32_t client_id)
266 {
267  // find list item that is not the connection item
268  // search through listbox
269  for (C4GUI::Element *list_item = GetFirst(); list_item; list_item = list_item->GetNext())
270  {
271  // only playerlistitems in this box
272  ListItem *list_item2 = static_cast<ListItem *>(list_item);
273  if (list_item2->GetClientID() == client_id)
274  if (list_item2->GetConnectionID() == -1)
275  return static_cast<ClientListItem *>(list_item2);
276  }
277  // nothing found
278  return nullptr;
279 }
280 
281 void C4Network2ClientListBox::ClientListItem::OnButtonActivate(C4GUI::Control *pButton)
282 {
283  // league: Do not deactivate clients with players
284  if (Game.Parameters.isLeague() && ::Players.GetAtClient(iClientID))
285  {
286  Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE"));
287  return;
288  }
289  // change to status that is not currently shown
291 }
292 
293 void C4Network2ClientListBox::ClientListItem::OnButtonKick(C4GUI::Control *pButton)
294 {
295  // try kick
296  // league: Kick needs voting
297  if (Game.Parameters.isLeague() && ::Players.GetAtClient(iClientID))
298  ::Network.Vote(VT_Kick, true, iClientID);
299  else
300  Game.Clients.CtrlRemove(GetClient(), LoadResStr(pForDlg->IsStartup() ? "IDS_MSG_KICKFROMSTARTUPDLG" : "IDS_MSG_KICKFROMCLIENTLIST"));
301 }
302 
303 void C4Network2ClientListBox::ClientListItem::SetSoundIcon()
304 {
305  // remember time for reset
306  last_sound_time = time(nullptr);
307  // force icon
308  Update();
309 }
310 
311 
312 // --------------------------------------------------
313 // C4Network2ClientListBox::ConnectionListItem
314 
315 C4Network2ClientListBox::ConnectionListItem::ConnectionListItem(class C4Network2ClientListBox *pForDlg, int32_t iClientID, int32_t iConnectionID) // ctor
316  : ListItem(pForDlg, iClientID), iConnID(iConnectionID), pDesc(nullptr), pPing(nullptr), pReconnectBtn(nullptr), pDisconnectBtn(nullptr)
317 {
318  // get size
320  int iIconSize = rUseFont.GetLineHeight();
321  int iWidth = pForDlg->GetItemWidth();
322  int iVerticalIndent = 2;
323  SetBounds(C4Rect(0, 0, iWidth, iIconSize+2*iVerticalIndent));
324  C4GUI::ComponentAligner ca(GetContainedClientRect(), 0,iVerticalIndent);
325  // left indent
326  ca.ExpandLeft(-iIconSize*2);
327  // create subcomponents
328  // reconnect/disconnect buttons
329  if (!Game.Parameters.isLeague())
330  {
331  pDisconnectBtn = new C4GUI::CallbackButtonEx<C4Network2ClientListBox::ConnectionListItem, C4GUI::IconButton>(C4GUI::Ico_Disconnect, ca.GetFromRight(iIconSize, iIconSize), 0, this, &ConnectionListItem::OnButtonDisconnect);
332  pDisconnectBtn->SetToolTip(LoadResStr("IDS_MENU_DISCONNECT"));
333  }
334  else
335  pDisconnectBtn = nullptr;
336  // ping time
337  int32_t sx=40, sy=iIconSize;
338  rUseFont.GetTextExtent("???? ms", sx,sy, true);
339  pPing = new C4GUI::Label("???", ca.GetFromRight(sx, sy), ARight);
340  pPing->SetToolTip(LoadResStr("IDS_NET_CONTROL_PING"));
341  // main description item
342  pDesc = new C4GUI::Label("???", ca.GetAll(), ALeft);
343  // add components
344  AddElement(pDesc);
345  AddElement(pPing);
346  if (pDisconnectBtn) AddElement(pDisconnectBtn);
347  // add to listbox (will eventually get moved)
348  pForDlg->AddElement(this);
349  // first-time update
350  Update();
351 }
352 
353 C4Network2IOConnection *C4Network2ClientListBox::ConnectionListItem::GetConnection() const
354 {
355  // get connection by connection ID
356  C4Network2Client *pNetClient = ::Network.Clients.GetClientByID(iClientID);
357  if (!pNetClient) return nullptr;
358  if (iConnID == 0) return pNetClient->getDataConn();
359  if (iConnID == 1) return pNetClient->getMsgConn();
360  return nullptr;
361 }
362 
363 void C4Network2ClientListBox::ConnectionListItem::Update()
364 {
365  C4Network2IOConnection *pConn = GetConnection();
366  if (!pConn)
367  {
368  // No connection: Shouldn't happen
369  pDesc->SetText("???");
370  pPing->SetText("???");
371  return;
372  }
373  // update connection ping
374  int iPing = pConn->getLag();
375  pPing->SetText(FormatString("%d ms", iPing).getData());
376  // update description
377  // get connection usage
378  const char *szConnType;
379  C4Network2Client *pNetClient = ::Network.Clients.GetClientByID(iClientID);
380  if (pNetClient->getDataConn() == pNetClient->getMsgConn())
381  szConnType = "Data/Msg";
382  else if (iConnID)
383  szConnType = "Msg";
384  else
385  szConnType = "Data";
386  // display info
387  pDesc->SetText(FormatString("%s: %s (%s l%d)",
388  szConnType,
390  pConn->getPeerAddr().ToString().getData(),
391  pConn->getPacketLoss()).getData());
392 }
393 
394 void C4Network2ClientListBox::ConnectionListItem::OnButtonDisconnect(C4GUI::Control *pButton)
395 {
396  // close connection
397  C4Network2IOConnection *pConn = GetConnection();
398  if (pConn)
399  {
400  pConn->Close();
401  }
402 }
403 
404 void C4Network2ClientListBox::ConnectionListItem::OnButtonReconnect(C4GUI::Control *pButton)
405 {
406  // 2do
407 }
408 
409 
410 // --------------------------------------------------
411 // C4Network2ClientListBox
412 
413 C4Network2ClientListBox::C4Network2ClientListBox(C4Rect &rcBounds, bool fStartup) : ListBox(rcBounds), fStartup(fStartup)
414 {
415  // hook into timer callback
416  Application.Add(this);
417  // initial update
418  Update();
419 }
420 
422 {
423  Application.Remove(this);
424 }
425 
427 {
428  // sync with client list
429  ListItem *pItem = static_cast<ListItem *>(pClientWindow->GetFirst()), *pNext;
430  const C4Client *pClient = nullptr;
431  while ((pClient = Game.Clients.getClient(pClient)))
432  {
433  // skip host in startup board
434  if (IsStartup() && pClient->isHost()) continue;
435  // deleted client(s) present? this will also delete unneeded client connections of previous client
436  while (pItem && (pItem->GetClientID() < pClient->getID()))
437  {
438  pNext = static_cast<ListItem *>(pItem->GetNext());
439  delete pItem; pItem = pNext;
440  }
441  // same present for update?
442  // need not check for connection ID, because a client item will always be placed before the corresponding connection items
443  if (pItem && pItem->GetClientID() == pClient->getID())
444  {
445  pItem->Update();
446  pItem = static_cast<ListItem *>(pItem->GetNext());
447  }
448  else
449  // not present: insert (or add if pItem=nullptr)
450  InsertElement(new ClientListItem(this, pClient->getID()), pItem);
451  // update connections for client
452  // but no connections in startup board
453  if (IsStartup()) continue;
454  // enumerate client connections
455  C4Network2Client *pNetClient = pClient->getNetClient();
456  if (!pNetClient) continue; // local client does not have connections
457  C4Network2IOConnection *pLastConn = nullptr;
458  for (int i = 0; i<2; ++i)
459  {
460  C4Network2IOConnection *pConn = i ? pNetClient->getMsgConn() : pNetClient->getDataConn();
461  if (!pConn) continue;
462  if (pConn == pLastConn) continue; // combined connection: Display only one
463  pLastConn = pConn;
464  // del leading items
465  while (pItem && ((pItem->GetClientID() < pClient->getID()) || ((pItem->GetClientID() == pClient->getID()) && (pItem->GetConnectionID() < i))))
466  {
467  pNext = static_cast<ListItem *>(pItem->GetNext());
468  delete pItem; pItem = pNext;
469  }
470  // update connection item
471  if (pItem && pItem->GetClientID() == pClient->getID() && pItem->GetConnectionID() == i)
472  {
473  pItem->Update();
474  pItem = static_cast<ListItem *>(pItem->GetNext());
475  }
476  else
477  {
478  // new connection: create it
479  InsertElement(new ConnectionListItem(this, pClient->getID(), i), pItem);
480  }
481  }
482  }
483  // del trailing items
484  while (pItem)
485  {
486  pNext = static_cast<ListItem *>(pItem->GetNext());
487  delete pItem; pItem = pNext;
488  }
489 }
490 
492 {
493  // sound icon on client element
494  ClientListItem *item = GetClientListItem(client_id);
495  if (item) item->SetSoundIcon();
496 }
497 
498 
499 // --------------------------------------------------
500 // C4Network2ClientListDlg
501 
502 // singleton
503 C4Network2ClientListDlg *C4Network2ClientListDlg::pInstance = nullptr;
504 
506  : Dialog(::pGUI->GetPreferredDlgRect().Wdt*3/4, ::pGUI->GetPreferredDlgRect().Hgt*3/4, LoadResStr("IDS_NET_CAPTION"), false)
507 {
508  // component layout
509  CStdFont *pUseFont = &::GraphicsResource.TextFont;
511  C4Rect rcStatus = caAll.GetFromBottom(pUseFont->GetLineHeight());
512  // create game options; max 1/2 of dialog height
513  pGameOptions = new C4GameOptionsList(caAll.GetFromTop(caAll.GetInnerHeight()/2), true, C4GameOptionsList::GOLS_Runtime);
514  pGameOptions->SetDecoration(false, nullptr, true, false);
515  pGameOptions->SetSelectionDiabled();
516  // but resize to actually used height
517  int32_t iFreedHeight = pGameOptions->ContractToElementHeight();
518  caAll.ExpandTop(iFreedHeight);
519  AddElement(pGameOptions);
520  // create client list box
521  AddElement(pListBox = new C4Network2ClientListBox(caAll.GetAll(), false));
522  // create status label
523  AddElement(pStatusLabel = new C4GUI::Label("", rcStatus));
524  // add timer
525  Application.Add(this);
526  // initial update
527  Update();
528 }
529 
531 {
532  if (this==pInstance) pInstance=nullptr; Application.Remove(this);
533 }
534 
536 {
537  // Compose status text
538  StdStrBuf sStatusText;
539  sStatusText.Format("Tick %d, Behind %d, Rate %d, PreSend %d, ACT: %d",
543  // Update status label
544  pStatusLabel->SetText(sStatusText.getData());
545 }
546 
548 {
549  // toggle off?
550  if (pInstance) { pInstance->Close(true); return true; }
551  // toggle on!
553 }
554 
556 {
557  if (singer) pListBox->SetClientSoundIcon(singer->getID());
558 }
559 
560 
561 // --------------------------------------------------
562 // C4Network2StartWaitDlg
563 
565  : C4GUI::Dialog(DialogWidth, DialogHeight, LoadResStr("IDS_NET_CAPTION"), false), pClientListBox(nullptr)
566 {
569  // create top label
570  C4GUI::Label *pLbl;
571  AddElement(pLbl = new C4GUI::Label(LoadResStr("IDS_NET_WAITFORSTART"), caAll.GetFromTop(25), ACenter));
572  // create client list box
573  AddElement(pClientListBox = new C4Network2ClientListBox(caAll.GetAll(), true));
574  // place abort button
575  C4GUI::Button *pBtnAbort = new C4GUI::CancelButton(caButtonArea.GetCentered(C4GUI_DefButtonWdt, C4GUI_ButtonHgt));
576  AddElement(pBtnAbort);
577 }
578 
579 
580 
581 // ---------------------------------------------------
582 // C4GameOptionButtons
583 
584 C4GameOptionButtons::C4GameOptionButtons(const C4Rect &rcBounds, bool fNetwork, bool fHost, bool fLobby)
585  : C4GUI::Window(), fNetwork(fNetwork), fHost(fHost), fLobby(fLobby), fCountdown(false)
586 {
587  SetBounds(rcBounds);
588  // calculate button size from area
589  int32_t iButtonCount = fNetwork ? fHost ? 6 : 3 : 2;
590  int32_t iIconSize = std::min<int32_t>(C4GUI_IconExHgt, rcBounds.Hgt), iIconSpacing = rcBounds.Wdt/(rcBounds.Wdt >= 400 ? 64 : 128);
591  if ((iIconSize+iIconSpacing*2)*iButtonCount > rcBounds.Wdt)
592  {
593  if (iIconSize*iButtonCount <= rcBounds.Wdt)
594  {
595  iIconSpacing = std::max<int32_t>(0, (rcBounds.Wdt-iIconSize*iButtonCount)/(iButtonCount*2)-1);
596  }
597  else
598  {
599  iIconSpacing = 0;
600  iIconSize = rcBounds.Wdt / iButtonCount;
601  }
602  }
603  C4GUI::ComponentAligner caButtonArea(rcBounds,0,0,true);
604  C4GUI::ComponentAligner caButtons(caButtonArea.GetCentered((iIconSize+2*iIconSpacing)*iButtonCount, iIconSize),iIconSpacing,0);
605  // add buttons
606  if (fNetwork && fHost)
607  {
608  bool fIsInternet = !!Config.Network.MasterServerSignUp, fIsDisabled = false;
609  // league currently implies master server signup, and can thus not be turned off
610  if (fLobby && Game.Parameters.isLeague())
611  {
612  fIsInternet = true;
613  fIsDisabled = true;
614  }
615  btnInternet = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(fIsInternet ? C4GUI::Ico_Ex_InternetOn : C4GUI::Ico_Ex_InternetOff, caButtons.GetFromLeft(iIconSize, iIconSize), LoadResStr("IDS_DLGTIP_STARTINTERNETGAME"), &C4GameOptionButtons::OnBtnInternet, this);
616  btnInternet->SetEnabled(!fIsDisabled);
617  AddElement(btnInternet);
618  }
619  else btnInternet = nullptr;
620  bool fIsLeague = false;
621  // League button
622  if (fNetwork)
623  {
624  C4GUI::Icons eLeagueIcon;
625  fIsLeague = fLobby ? Game.Parameters.isLeague() : !!Config.Network.LeagueServerSignUp;
626  eLeagueIcon = fIsLeague ? C4GUI::Ico_Ex_LeagueOn : C4GUI::Ico_Ex_LeagueOff;
627  btnLeague = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(eLeagueIcon, caButtons.GetFromLeft(iIconSize, iIconSize), LoadResStr("IDS_DLGTIP_STARTLEAGUEGAME"), &C4GameOptionButtons::OnBtnLeague, this);
628  btnLeague->SetEnabled(fHost && !fLobby);
629  AddElement(btnLeague);
630  }
631  else btnLeague=nullptr;
632  if (fNetwork && fHost)
633  {
634  btnPassword = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(::Network.isPassworded() ? C4GUI::Ico_Ex_Locked : C4GUI::Ico_Ex_Unlocked, caButtons.GetFromLeft(iIconSize, iIconSize), LoadResStr("IDS_NET_PASSWORD_DESC"), &C4GameOptionButtons::OnBtnPassword, this);
635  AddElement(btnPassword);
636  btnComment = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(C4GUI::Ico_Ex_Comment, caButtons.GetFromLeft(iIconSize, iIconSize), LoadResStr("IDS_DESC_COMMENTDESCRIPTIONFORTHIS"), &C4GameOptionButtons::OnBtnComment, this);
637  AddElement(btnComment);
638  }
639  else btnPassword=btnComment=nullptr;
640  btnRecord = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(Game.Record || fIsLeague ? C4GUI::Ico_Ex_RecordOn : C4GUI::Ico_Ex_RecordOff, caButtons.GetFromLeft(iIconSize, iIconSize), LoadResStr("IDS_DLGTIP_RECORD"), &C4GameOptionButtons::OnBtnRecord, this);
641  btnRecord->SetEnabled(!fIsLeague);
642  AddElement(btnRecord);
643 }
644 
646 {
647  if (!fNetwork || !fHost) return;
649  // in lobby mode, do actual termination from masterserver
650  if (fLobby)
651  {
652  if (fCheck)
653  {
654  fCheck = ::Network.LeagueSignupEnable();
655  }
656  else
657  {
659  }
660  }
662  // also update league button, because turning off masterserver also turns off the league
663  if (!fCheck)
664  {
666  if (btnLeague)
667  btnLeague->SetIcon(C4GUI::Ico_Ex_LeagueOff);
668  }
669  // re-set in config for the case of failure
671 }
672 
674 {
675  if (!fNetwork || !fHost) return;
678  if (!Game.Record) OnBtnRecord(btnRecord);
679  btnRecord->SetEnabled(!fCheck);
680  // if the league is turned on, the game must be signed up at the masterserver
681  if (fCheck && !Config.Network.MasterServerSignUp) OnBtnInternet(btnInternet);
682  // refresh options in scenario selection dialogue
684 }
685 
687 {
688  Game.Record = !Game.Record;
691 }
692 
694 {
695  if (!fNetwork || !fHost) return;
696  // password is currently set - a single click only clears the password
698  {
699  StdStrBuf empty;
700  OnPasswordSet(empty);
701  return;
702  }
703  // password button pressed: Show dialog to set/change current password
704  C4GUI::InputDialog *pDlg;
706  pDlg->SetMaxText(CFG_MaxString);
707  const char *szPassPreset = ::Network.GetPassword();
708  if (!szPassPreset || !*szPassPreset) szPassPreset = Config.Network.LastPassword;
709  if (*szPassPreset) pDlg->SetInputText(szPassPreset);
710 }
711 
713 {
714  // password input dialog answered with OK: Set/clear network password
715  const char *szPass;
716  ::Network.SetPassword(szPass=rsNewPassword.getData());
717  // update icon to reflect if a password is set
719  // remember password for next round
720  bool fHasPassword = (szPass && *szPass);
721  if (fHasPassword)
722  {
724  }
725  // acoustic feedback
726  C4GUI::GUISound("UI::Confirmed");
727 }
728 
730 {
731  // update icon to reflect if a password is set
732  const char *szPass = ::Network.GetPassword();
733  bool fHasPassword = szPass && *szPass;
734  btnPassword->SetIcon(fHasPassword ? C4GUI::Ico_Ex_Locked : C4GUI::Ico_Ex_Unlocked);
735 }
736 
738 {
739  // password button pressed: Show dialog to set/change current password
740  C4GUI::InputDialog *pDlg;
742  pDlg->SetMaxText(C4MaxComment);
744 }
745 
747 {
748  // check for change; no reference invalidation if not changed
749  if (rsNewComment == Config.Network.Comment) return;
750  // Set in configuration, update reference
751  Config.Network.Comment.CopyValidated(rsNewComment.getData());
753  // message feedback
754  Log(LoadResStr("IDS_NET_COMMENTCHANGED"));
755  // acoustic feedback
756  C4GUI::GUISound("UI::Confirmed");
757 }
758 
760 {
761  fCountdown = fToVal;
762 }
763 
764 // ---------------------------------------------------
765 // C4Chart
766 
767 int GetValueDecade(int iVal)
768 {
769  // get enclosing decade
770  int iDec = 1;
771  while (iVal) { iVal/=10; iDec*=10; }
772  return iDec;
773 }
774 
775 int GetAxisStepRange(int iRange, int iMaxSteps)
776 {
777  // try in steps of 5s and 10s
778  int iDec = GetValueDecade(iRange);
779  if (iDec == 1) return 1;
780  int iNextStepDivider = 2;
781  while (iDec>=iNextStepDivider && iNextStepDivider*iRange/iDec <= iMaxSteps)
782  {
783  iDec/=iNextStepDivider;
784  iNextStepDivider = 7 - iNextStepDivider;
785  }
786  return iDec;
787 }
788 
790 {
791  typedef C4Graph::ValueType ValueType;
792  typedef C4Graph::TimeType TimeType;
793  // transparent w/o graph
794  if (!pDisplayGraph) return;
795  int iSeriesCount = pDisplayGraph->GetSeriesCount();
796  if (!iSeriesCount) return;
797  assert(iSeriesCount>0);
798  StdStrBuf sbuf;
799  pDisplayGraph->Update(); // update averages, etc.
800  // calc metrics
802  int YAxisWdt = 5,
803  XAxisHgt = 15;
804 
805  const int AxisArrowLen = 6,
806  AxisMarkerLen = 5,
807  AxisArrowThickness = 3,
808  AxisArrowIndent= 2; // margin between axis arrow and last value
809  int32_t YAxisMinStepHgt, XAxisMinStepWdt;
810  // get value range
811  int iMinTime = pDisplayGraph->GetStartTime();
812  int iMaxTime = pDisplayGraph->GetEndTime() - 1;
813  if (iMinTime >= iMaxTime) return;
814  ValueType iMinVal = pDisplayGraph->GetMinValue();
815  ValueType iMaxVal = pDisplayGraph->GetMaxValue();
816  if (iMinVal == iMaxVal) ++iMaxVal;
817  if (iMinVal > 0 && iMaxVal/iMinVal >= 2) iMinVal = 0; // go zero-based if this creates less than 50% unused space
818  else if (iMaxVal < 0 && iMinVal/iMaxVal >= 2) iMaxVal = 0;
819  int ddv;
820  if (iMaxVal>0 && (ddv=GetValueDecade(int(iMaxVal))/50))
821  iMaxVal = ((iMaxVal-(iMaxVal>0))/ddv+(iMaxVal>0))*ddv;
822  if (iMinVal && (ddv=GetValueDecade(int(iMinVal))/50))
823  iMinVal = ((iMinVal-(iMinVal<0))/ddv+(iMinVal<0))*ddv;
824  ValueType dv=iMaxVal-iMinVal; TimeType dt=iMaxTime-iMinTime;
825  // axis calculations
826  sbuf.Format("-%d", (int) std::max(Abs(iMaxVal), Abs(iMinVal)));
827  rFont.GetTextExtent(sbuf.getData(), XAxisMinStepWdt, YAxisMinStepHgt, false);
828  YAxisWdt += XAxisMinStepWdt; XAxisHgt += YAxisMinStepHgt;
829  XAxisMinStepWdt += 2; YAxisMinStepHgt += 2;
830  int tw = rcBounds.Wdt - YAxisWdt;
831  int th = rcBounds.Hgt - XAxisHgt;
832  int tx = rcBounds.x + int(cgo.TargetX) + YAxisWdt;
833  int ty = rcBounds.y + int(cgo.TargetY);
834  // show a legend, if more than one graph is shown
835  if (iSeriesCount > 1)
836  {
837  int iSeries = 0; const C4Graph *pSeries;
838  int32_t iLegendWdt = 0, Q,W;
839  while ((pSeries = pDisplayGraph->GetSeries(iSeries++)))
840  {
841  rFont.GetTextExtent(pSeries->GetTitle(), W, Q, true);
842  iLegendWdt = std::max(iLegendWdt, W);
843  }
844  tw -= iLegendWdt+1;
845  iSeries = 0;
846  int iYLegendDraw = (th - iSeriesCount*Q)/2 + ty;
847  while ((pSeries = pDisplayGraph->GetSeries(iSeries++)))
848  {
849  pDraw->TextOut(pSeries->GetTitle(), rFont, 1.0f, cgo.Surface, tx+tw, iYLegendDraw, pSeries->GetColorDw() | 0xff000000, ALeft, true);
850  iYLegendDraw += Q;
851  }
852  }
853  // safety: too small?
854  if (tw < 10 || th < 10) return;
855  // draw axis
856  pDraw->DrawLineDw(cgo.Surface, tx, ty+th, tx+tw-1, ty+th, C4RGB(0x91, 0x91, 0x91));
857  pDraw->DrawLineDw(cgo.Surface, tx+tw-1, ty+th, tx+tw-1-AxisArrowLen, ty+th-AxisArrowThickness, C4RGB(0x91, 0x91, 0x91));
858  pDraw->DrawLineDw(cgo.Surface, tx+tw-1, ty+th, tx+tw-1-AxisArrowLen, ty+th+AxisArrowThickness, C4RGB(0x91, 0x91, 0x91));
859  pDraw->DrawLineDw(cgo.Surface, tx, ty, tx, ty+th, C4RGB(0x91, 0x91, 0x91));
860  pDraw->DrawLineDw(cgo.Surface, tx, ty, tx-AxisArrowThickness, ty+AxisArrowLen, C4RGB(0x91, 0x91, 0x91));
861  pDraw->DrawLineDw(cgo.Surface, tx, ty, tx+AxisArrowThickness, ty+AxisArrowLen, C4RGB(0x91, 0x91, 0x91));
862  tw -= AxisArrowLen + AxisArrowIndent;
863  th -= AxisArrowLen + AxisArrowIndent; ty += AxisArrowLen + AxisArrowIndent;
864  // do axis numbering
865  int iXAxisSteps = GetAxisStepRange(dt, tw / XAxisMinStepWdt),
866  iYAxisSteps = GetAxisStepRange(int(dv), th / YAxisMinStepHgt);
867  int iX, iY, iTime, iVal;
868  iY = 0;
869  iTime = ((iMinTime-(iMinTime>0))/iXAxisSteps+(iMinTime>0))*iXAxisSteps;
870  for (; iTime <= iMaxTime; iTime += iXAxisSteps)
871  {
872  iX = tx + tw * (iTime-iMinTime) / dt;
873  pDraw->DrawLineDw(cgo.Surface, iX, ty+th+1, iX, ty+th+AxisMarkerLen, C4RGB(0x91, 0x91, 0x91));
874  sbuf.Format("%d", (int) iTime);
875  pDraw->TextOut(sbuf.getData(), rFont, 1.0f, cgo.Surface, iX, ty+th+AxisMarkerLen, 0xff7f7f7f, ACenter, false);
876  }
877  iVal = int( ((iMinVal-(iMinVal>0))/iYAxisSteps+(iMinVal>0))*iYAxisSteps );
878  for (; iVal <= iMaxVal; iVal += iYAxisSteps)
879  {
880  iY = ty+th - int((iVal-iMinVal) / dv * th);
881  pDraw->DrawLineDw(cgo.Surface, tx-AxisMarkerLen, iY, tx-1, iY, C4RGB(0x91, 0x91, 0x91));
882  sbuf.Format("%d", (int) iVal);
883  pDraw->TextOut(sbuf.getData(), rFont, 1.0f, cgo.Surface, tx-AxisMarkerLen, iY-rFont.GetLineHeight()/2, 0xff7f7f7f, ARight, false);
884  }
885  // draw graph series(es)
886  int iSeries = 0;
887  while (const C4Graph *pSeries = pDisplayGraph->GetSeries(iSeries++))
888  {
889  int iThisMinTime = std::max(iMinTime, pSeries->GetStartTime());
890  int iThisMaxTime = std::min(iMaxTime, pSeries->GetEndTime());
891  bool fAnyVal = false;
892  for (iX = 0; iX<tw; ++iX)
893  {
894  iTime = iMinTime + dt*iX/tw;
895  if (!Inside(iTime, iThisMinTime, iThisMaxTime)) continue;
896  int iY2 = int((-pSeries->GetValue(iTime) + iMinVal) * th / dv) + ty+th;
897  if (fAnyVal) pDraw->DrawLineDw(cgo.Surface, (float) (tx+iX-1), (float) iY, (float) (tx+iX), (float) iY2, pSeries->GetColorDw() | 0xff000000);
898  iY = iY2;
899  fAnyVal = true;
900  }
901  }
902 }
903 
904 C4Chart::C4Chart(C4Rect &rcBounds) : Element(), pDisplayGraph(nullptr), fOwnGraph(false)
905 {
906  this->rcBounds = rcBounds;
907 }
908 
910 {
911  if (fOwnGraph && pDisplayGraph) delete pDisplayGraph;
912 }
913 
914 
915 // singleton
916 C4ChartDialog *C4ChartDialog::pChartDlg=nullptr;
917 
918 C4ChartDialog::C4ChartDialog() : Dialog(DialogWidth, DialogHeight, LoadResStr("IDS_NET_STATISTICS"), false), pChartTabular(nullptr)
919 {
920  // register singleton
921  pChartDlg = this;
922  // add main chart switch component
924  pChartTabular = new C4GUI::Tabular(caAll.GetAll(), C4GUI::Tabular::tbTop);
925  AddElement(pChartTabular);
926  // add some graphs as subcomponents
927  AddChart(StdStrBuf("oc"));
928  AddChart(StdStrBuf("FPS"));
929  AddChart(StdStrBuf("NetIO"));
930  if (::Network.isEnabled())
931  AddChart(StdStrBuf("Pings"));
932  AddChart(StdStrBuf("Control"));
933  AddChart(StdStrBuf("APM"));
934 }
935 
936 void C4ChartDialog::AddChart(const StdStrBuf &rszName)
937 {
938  // get graph by name
939  if (!Game.pNetworkStatistics || !pChartTabular) return;
940  bool fOwnGraph = false;
941  C4Graph *pGraph = Game.pNetworkStatistics->GetGraphByName(rszName, fOwnGraph);
942  if (!pGraph) return;
943  // add sheet for name
944  C4GUI::Tabular::Sheet *pSheet = pChartTabular->AddSheet(rszName.getData());
945  if (!pSheet) { if (fOwnGraph) delete pGraph; return; }
946  // add chart to sheet
947  C4Chart *pNewChart = new C4Chart(pSheet->GetClientRect());
948  pNewChart->SetGraph(pGraph, fOwnGraph);
949  pSheet->AddElement(pNewChart);
950 }
951 
953 {
954  // close if open
955  if (pChartDlg) { pChartDlg->Close(false); return; }
956  // otherwise, open
957  C4ChartDialog *pDlg = new C4ChartDialog();
958  if (!::pGUI->ShowRemoveDlg(pDlg)) if (pChartDlg) delete pChartDlg;
959 }
const C4Network2Address & getAddr(int32_t i) const
const char * getData() const
Definition: StdBuf.h:450
const char * GetPassword() const
Definition: C4Network2.h:217
const C4Graph * pDisplayGraph
bool fHost
Definition: TstC4NetIO.cpp:34
void SetPassword(const char *szToPassword)
Definition: C4Network2.cpp:794
C4Network2ClientDlg(int iForClientID)
void OnBtnPassword(C4GUI::Control *btn)
#define C4GUI_ButtonAreaHgt
Definition: C4Gui.h:113
C4Config Config
Definition: C4Config.cpp:837
void ExpandTop(int32_t iByHgt)
Definition: C4Gui.h:2808
int GetLineHeight() const
Definition: C4FontLoader.h:132
C4Chart(C4Rect &rcBounds)
void GUISound(const char *szSound)
Definition: C4Gui.cpp:1178
#define C4GUI_ButtonHgt
Definition: C4Gui.h:111
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:122
void GetAll(C4Rect &rcOut)
Definition: C4Gui.cpp:1128
C4Network2Client * GetClientByID(int32_t iID) const
void SetCountdown(bool fToVal)
virtual const C4Graph * GetSeries(int iIndex) const =0
int32_t ControlTick
Definition: C4GameControl.h:89
bool isHost() const
Definition: C4Network2.h:209
C4Network2IO NetIO
Definition: C4Network2.h:110
int32_t GetInnerHeight() const
Definition: C4Gui.h:2806
C4Game Game
Definition: C4Globals.cpp:52
C4ConfigGeneral General
Definition: C4Config.h:252
C4Network2IOConnection * getMsgConn() const
#define C4GUI_IconExHgt
Definition: C4Gui.h:96
bool AddElement(Element *pChild, int32_t iIndent=0)
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:410
bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
Definition: C4Draw.cpp:570
bool isActivated() const
Definition: C4Client.h:110
bool InsertElement(Element *pChild, Element *pInsertBefore, int32_t iIndent=0)
ValidatedStdCopyStrBuf< C4InVal::VAL_Comment > Comment
Definition: C4Config.h:147
virtual void Update() const
StdStrBuf ToString(int flags=0) const
Definition: C4NetIO.cpp:605
void Close(bool fOK)
const int ARight
Definition: C4Surface.h:43
bool isHost() const
Definition: C4Client.h:106
bool ShowRemoveDlg(Dialog *pDlg)
void Vote(C4ControlVoteType eType, bool fApprove=true, int32_t iData=0)
Definition: C4Rect.h:29
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:181
virtual C4Rect & GetClientRect()
Definition: C4Gui.h:864
void AddElement(Element *pChild)
Element * GetFirst()
Definition: C4Gui.h:1571
void SetClientSoundIcon(int32_t client_id)
C4Network2Client * getNetClient() const
Definition: C4Client.h:117
C4Rect GetContainedClientRect()
Definition: C4Gui.h:448
void SetGraph(const C4Graph *pNewGraph, bool fOwn)
C4GraphicsResource GraphicsResource
void SetDecoration(bool fDrawBG, ScrollBarFacets *pToGfx, bool fAutoScroll, bool fDrawBorder=false)
Definition: C4Gui.h:1566
void CtrlRemove(const C4Client *pClient, const char *szReason)
Definition: C4Client.cpp:350
C4GameParameters & Parameters
Definition: C4Game.h:69
void Add(StdSchedulerProc *pProc)
const C4NetIO::addr_t & getPeerAddr() const
Definition: C4Network2IO.h:264
void DrawLineDw(C4Surface *sfcTarget, float x1, float y1, float x2, float y2, DWORD dwClr, float width=1.0f)
Definition: C4Draw.cpp:617
C4Player * GetAtClient(int iClient, int iIndex=0) const
virtual int GetSeriesCount() const =0
void OnBtnLeague(C4GUI::Control *btn)
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
C4Network2IOConnection * getDataConn() const
T Clamp(T bval, T lbound, T rbound)
Definition: Standard.h:46
void AppendFormat(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:197
bool isConnected() const
int32_t getID() const
Definition: C4Client.h:105
int32_t Wdt
Definition: C4Rect.h:32
int32_t GetBehind(int32_t iTick) const
int32_t ClientPerfStat(int32_t iClientID)
int32_t getAvgControlSendTime() const
void SetMaxText(int32_t iMaxLen)
Definition: C4Gui.h:2419
void OnLeagueOptionChanged()
Definition: C4Startup.cpp:356
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1194
void OnBtnInternet(C4GUI::Control *btn)
const unsigned int C4MaxComment
C4Network2 Network
Definition: C4Globals.cpp:53
bool GetFromTop(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1062
const char * LoadResStrNoAmp(const char *id)
Definition: StdResStr2.cpp:24
int32_t y
Definition: C4Rect.h:32
Element * GetFirst()
Definition: C4Gui.h:829
int iCnt
Definition: TstC4NetIO.cpp:35
C4GameOptionButtons(const C4Rect &rcBounds, bool fNetwork, bool fHost, bool fLobby)
const int ACenter
Definition: C4Surface.h:43
virtual ValueType GetMinValue() const =0
void InvalidateReference()
C4GameControl Control
C4Rect GetToprightCornerRect(int32_t iWidth=16, int32_t iHeight=16, int32_t iHIndent=4, int32_t iVIndent=4, int32_t iIndexX=0)
Definition: C4Gui.cpp:400
int32_t DefRec
Definition: C4Config.h:48
C4Rect rcBounds
Definition: C4Gui.h:385
void DoInput(C4PacketType eCtrlType, C4ControlPacket *pPkt, C4ControlDeliveryType eDelivery)
bool LeagueSignupEnable()
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:527
char LastPassword[CFG_MaxString+1]
Definition: C4Config.h:159
C4PlayerList Players
int getPingTime() const
Definition: C4Network2IO.h:273
C4ConfigNetwork Network
Definition: C4Config.h:256
#define C4GUI_DefButtonWdt
Definition: C4Gui.h:114
void OnBtnRecord(C4GUI::Control *btn)
C4Draw * pDraw
Definition: C4Draw.cpp:45
void OnBtnComment(C4GUI::Control *btn)
#define C4RGB(r, g, b)
Definition: StdColors.h:28
StdStrBuf GetActivePlayerNames(bool fCountInvisible, int32_t iAtClientID=-1) const
void SetInputText(const char *szToText)
void OnPasswordSet(const StdStrBuf &rsNewPassword)
bool isEnabled() const
Definition: C4Network2.h:203
C4Rect & GetBounds()
Definition: C4Gui.h:445
bool isReady() const
int32_t LeagueServerSignUp
Definition: C4Config.h:152
Icons
Definition: C4Gui.h:637
int32_t getControlPreSend() const
int32_t MasterServerSignUp
Definition: C4Config.h:148
int32_t x
Definition: C4Rect.h:32
void Ref(const char *pnData)
Definition: StdBuf.h:463
void Remove(StdSchedulerProc *pProc)
C4Network2ClientList Clients
Definition: C4Network2.h:116
Element * GetNext() const
Definition: C4Gui.h:449
float TargetX
Definition: C4Facet.h:167
C4PlayerInfoList & PlayerInfos
Definition: C4Game.h:73
virtual void UpdateText()
virtual TimeType GetStartTime() const =0
C4Client * getClientByID(int32_t iID) const
Definition: C4Client.cpp:217
virtual ~C4Chart()
int32_t GetItemWidth()
Definition: C4Gui.h:1545
virtual ValueType GetMaxValue() const =0
const char * getName() const
Definition: C4Client.h:107
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
float ValueType
bool ClientReady(int32_t iClientID, int32_t iTick)
int32_t ContractToElementHeight()
C4GameControlNetwork Network
Definition: C4GameControl.h:67
int getPacketLoss() const
Definition: C4Network2IO.h:277
int GetValueDecade(int iVal)
bool isLocal() const
Definition: C4Client.h:116
StdStrBuf toString() const
const int ALeft
Definition: C4Surface.h:43
C4Network2ClientStatus getStatus() const
int GetAxisStepRange(int iRange, int iMaxSteps)
DWORD GetColorDw() const
const char * getNick() const
Definition: C4Client.h:109
bool Log(const char *szMessage)
Definition: C4Log.cpp:195
virtual void DrawElement(C4TargetFacet &cgo)
void AddLineFmt(const char *szFmtString,...) GNUC_FORMAT_ATTRIBUTE_O
C4ClientList & Clients
Definition: C4Game.h:71
#define C4GUI_DefDlgIndent
Definition: C4Gui.h:132
static C4Startup * Get()
Definition: C4Startup.h:133
bool Record
Definition: C4Game.h:125
bool isPassworded() const
Definition: C4Network2.h:218
bool isLeague() const
static void Toggle()
Sheet * AddSheet(const char *szTitle, int32_t icoTitle=Ico_None)
void SetIcon(Icons eUseIcon)
virtual Screen * GetScreen()
Definition: C4Gui.cpp:290
Element * pNext
Definition: C4Gui.h:377
int32_t Hgt
Definition: C4Rect.h:32
T Abs(T val)
Definition: Standard.h:44
C4Surface * Surface
Definition: C4Facet.h:119
C4Network2ClientListBox(C4Rect &rcBounds, bool fStartup)
float TargetY
Definition: C4Facet.h:167
void AddLine(const char *szText)
void OnSound(class C4Client *singer)
std::unique_ptr< C4Network2Stats > pNetworkStatistics
Definition: C4Game.h:97
const char * getNetIOName(C4NetIO *pNetIO)
C4NetIO * getNetClass() const
Definition: C4Network2IO.h:262
C4Client * getClient(const C4Client *pAfter=nullptr) const
Definition: C4Client.h:160
int32_t getAddrCnt() const
bool Inside(T ival, U lbound, V rbound)
Definition: Standard.h:45
void LeagueSignupDisable()
virtual TimeType GetEndTime() const =0
void OnCommentSet(const StdStrBuf &rsNewComment)
void CopyValidated(const char *szFromVal)
C4Application Application
Definition: C4Globals.cpp:44
bool GetCentered(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1136
bool GetFromBottom(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1112
void SetSelectionDiabled(bool fToVal=true)
Definition: C4Gui.h:1568
int32_t ControlRate
Definition: C4GameControl.h:88
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277
const char * GetTitle() const
ScrollWindow * pClientWindow
Definition: C4Gui.h:1509
void SetEnabled(bool fToVal)
Definition: C4Gui.h:1131