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