OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4Network2Players.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 // NET2 network player management
17 // see header for some additional information
18 // 2do: Handle client joins after game go but before runtime join (Frame 0)?
19 // Those will not receive a player info list right in time
20 
21 #include "C4Include.h"
23 #include "control/C4PlayerInfo.h"
24 #include "gui/C4GameLobby.h"
25 #include "game/C4Game.h"
26 #include "network/C4Network2.h"
27 #include "control/C4GameControl.h"
28 #include "control/C4RoundResults.h"
29 
30 #include "control/C4Control.h"
31 
32 // *** C4Network2Players
33 
34 C4Network2Players::C4Network2Players() : rInfoList(Game.Parameters.PlayerInfos)
35 {
36  // ctor - init rInfoList-ref to only
37 }
38 
40 {
41  // caution: In this call, only local players are joined
42  // remote players may have been added already for runtime joins
43  // not in replay
44  if (Game.C4S.Head.Replay) return;
45  // network only
46  assert(::Network.isEnabled());
47  // must init before game is running
48  assert(!Game.IsRunning);
49  if (::Network.isHost())
50  {
51  // host: Rejoin script players from savegame before joining local players so team distribution is done correctly
52  // But prepare empty host list before recreation
53  JoinLocalPlayer("", true);
56  }
57  else
58  {
59  // Client: join the local player(s)
61  }
62 }
63 
65 {
66  // nothing...
67 }
68 
69 bool C4Network2Players::JoinLocalPlayer(const char *szLocalPlayerFilename, bool initial)
70 {
71  // ignore in replay
72  // shouldn't even come here though
73  assert(!Game.C4S.Head.Replay);
74  if (Game.C4S.Head.Replay) return false;
75  // if observing: don't try
76  if (Game.Clients.getLocal()->isObserver()) return false;
77  // network only
78  assert(::Network.isEnabled());
79  // create join info packet
80  C4ClientPlayerInfos JoinInfo(szLocalPlayerFilename, !initial);
81  // league game: get authentication for players
82  if (Game.Parameters.isLeague())
83  for (int i = 0; i < JoinInfo.GetPlayerCount(); i++)
84  {
85  C4PlayerInfo *pInfo = JoinInfo.GetPlayerInfo(i);
86  if (!::Network.LeaguePlrAuth(pInfo))
87  {
88  JoinInfo.RemoveIndexedInfo(i);
89  i--;
90  }
91  }
92  // host or client?
93  if (::Network.isHost())
94  {
95  // error joining players? Zero players is OK for initial packet; marks host as observer
96  if (!initial && !JoinInfo.GetPlayerCount()) return false;
97  // handle it as a direct request
98  HandlePlayerInfoUpdRequest(&JoinInfo, true);
99  }
100  else
101  {
102  // clients request initial joins at host only
103  // create player info for local player joins
104  C4PacketPlayerInfoUpdRequest JoinRequest(JoinInfo);
105  // any players to join? Zero players is OK for initial packet; marks client as observer
106  // it's also necessary to send the empty player info packet, so the host will answer
107  // with infos of all other clients
108  if (!initial && !JoinRequest.Info.GetPlayerCount()) return false;
110  // request activation
111  if (JoinRequest.Info.GetPlayerCount() && !Game.Clients.getLocal()->isActivated())
113  }
114  // done, success
115  return true;
116 }
117 
119 {
120  // network only
121  assert(::Network.isEnabled());
122  // host or client?
123  if (::Network.isHost())
124  {
125  // host processes directly
126  HandlePlayerInfoUpdRequest(&rRequest, true);
127  }
128  else
129  {
130  // client sends request to host
131  C4PacketPlayerInfoUpdRequest UpdateRequest(rRequest);
133  }
134 }
135 
136 void C4Network2Players::HandlePlayerInfoUpdRequest(const class C4ClientPlayerInfos *pInfoPacket, bool fByHost)
137 {
138  // network host only
139  assert(::Network.isEnabled());
140  assert(::Network.isHost());
141  // copy client infos (need to be adjusted)
142  C4ClientPlayerInfos OwnInfoPacket(*pInfoPacket);
143  // safety: check any duplicate, unjoined players first
144  // check those with unassigned IDs only, so update packets won't be rejected by this
145  if (!OwnInfoPacket.IsInitialPacket())
146  {
147  C4ClientPlayerInfos *pExistingClientInfo = rInfoList.GetInfoByClientID(OwnInfoPacket.GetClientID());
148  if (pExistingClientInfo)
149  {
150  int iCnt=OwnInfoPacket.GetPlayerCount(); C4PlayerInfo *pPlrInfo;
151  C4Network2Res *pRes;
152  while (iCnt--) if ((pPlrInfo=OwnInfoPacket.GetPlayerInfo(iCnt)))
153  if (!pPlrInfo->GetID()) if ((pRes = pPlrInfo->GetRes()))
154  if (pExistingClientInfo->GetPlayerInfoByRes(pRes->getResID()))
155  {
156  // double join: simply deny without message
157 #ifdef _DEBUG
158  Log("Network: Duplicate player join rejected!");
159 #endif
160  OwnInfoPacket.RemoveIndexedInfo(iCnt);
161  }
162  }
163  if (!OwnInfoPacket.GetPlayerCount())
164  {
165  // player join request without players: probably all removed because doubled
166 #ifdef _DEBUG
167  Log("Network: Empty player join request ignored!");
168 #endif
169  return;
170  }
171  }
172  // assign player IDs
173  if (!rInfoList.AssignPlayerIDs(&OwnInfoPacket) && OwnInfoPacket.IsAddPacket())
174  {
175  // no players could be joined in an add request: probably because the maximum player limit has been reached
176  return;
177  }
178  // check doubled savegame player usage
179  UpdateSavegameAssignments(&OwnInfoPacket);
180  // update teams
181  rInfoList.AssignTeams(&OwnInfoPacket, fByHost);
182  // update any other player colors and names
183  // this may only change colors and names of all unjoined players (which is all players in lobby mode)
184  // any affected players will get an updated-flag
185  rInfoList.UpdatePlayerAttributes(&OwnInfoPacket, true);
186  // league score gains may now be different
187  rInfoList.ResetLeagueProjectedGain(true);
188  int32_t iPlrInfo = 0;
189  C4PlayerInfo *pPlrInfo;
190  while ((pPlrInfo = OwnInfoPacket.GetPlayerInfo(iPlrInfo++))) pPlrInfo->ResetLeagueProjectedGain();
191  if (Game.Parameters.isLeague())
192  {
193  // check league authentication for new players
194  for (int i = 0; i < OwnInfoPacket.GetPlayerCount(); i++)
195  {
196  if (!rInfoList.GetPlayerInfoByID(OwnInfoPacket.GetPlayerInfo(i)->GetID()))
197  {
198  C4PlayerInfo *pInfo = OwnInfoPacket.GetPlayerInfo(i);
199  // remove normal (non-script) player infos without authentication or when not in the lobby
200  if (pInfo->GetType() != C4PT_Script && (!::Network.isLobbyActive() || !::Network.LeaguePlrAuthCheck(pInfo)))
201  {
202  OwnInfoPacket.RemoveIndexedInfo(i);
203  i--;
204  }
205  else
206  // always reset authentication ID after check - it's not needed anymore
207  pInfo->SetAuthID("");
208  }
209  }
210  }
211  // send updates to all other clients and reset update flags
213  // finally, add new player join as direct input
214  // this will add the player infos directly on host side (DirectExec as a subcall),
215  // so future player join request will take the other joined clients into consideration
216  // when assigning player colors, etc.; it will also start resource loading
217  // in running mode, this call will also put the actual player joins into the queue
219  // notify lobby of updates
221  if (pLobby) pLobby->OnPlayersChange();
222 }
223 
225 {
226  // network only
227  assert(::Network.isEnabled());
228  // copy client player infos out of packet to be used in local list
229  C4ClientPlayerInfos *pClientInfo = new C4ClientPlayerInfos(rInfoPacket);
230  // add client info to local player info list - eventually deleting pClientInfo and
231  // returning a pointer to the new info structure when multiple player infos are merged
232  // may also replace existing info, if this is an update-call
233  pClientInfo = rInfoList.AddInfo(pClientInfo);
234  // make sure team list reflects teams set in player infos
236  Game.Teams.RecheckTeams(); // recheck random teams - if a player left, teams may need to be rebalanced
237  // make sure resources are loaded for those players
238  rInfoList.LoadResources();
239  // get associated client - note that pClientInfo might be nullptr for empty packets that got discarded
240  if (pClientInfo)
241  {
242  const C4Client *pClient = Game.Clients.getClientByID(pClientInfo->GetClientID());
243  // host, game running and client active already?
244  if (::Network.isHost() && ::Network.isRunning() && pClient && pClient->isActivated())
245  {
246  // then join the players immediately
247  JoinUnjoinedPlayersInControlQueue(pClientInfo);
248  }
249  }
250  // adding the player may have invalidated other players (through team settings). Send them.
252  // lobby: update players
254  if (pLobby) pLobby->OnPlayersChange();
255  // invalidate reference
257 }
258 
260 {
261  // check all clients for update
262  C4ClientPlayerInfos *pUpdInfo; int i=0;
263  while ((pUpdInfo = rInfoList.GetIndexedInfo(i++)))
264  if (pUpdInfo->IsUpdated())
265  {
266  pUpdInfo->ResetUpdated();
267  C4ControlPlayerInfo *pkSend = new C4ControlPlayerInfo(*pUpdInfo);
268  // send info to all
270  }
271 }
272 
273 void C4Network2Players::UpdateSavegameAssignments(C4ClientPlayerInfos *pNewInfo)
274 {
275  // safety
276  if (!pNewInfo) return;
277  // check all joins of new info; backwards so they can be deleted
278  C4PlayerInfo *pInfo, *pInfo2, *pSaveInfo; int i=pNewInfo->GetPlayerCount(), j, id;
279  while (i--) if ((pInfo = pNewInfo->GetPlayerInfo(i)))
280  if ((id=pInfo->GetAssociatedSavegamePlayerID()))
281  {
282  // check for non-existant savegame players
283  if (!(pSaveInfo=Game.RestorePlayerInfos.GetPlayerInfoByID(id)))
284  {
285  pInfo->SetAssociatedSavegamePlayer(id=0);
286  pNewInfo->SetUpdated();
287  }
288  // check for duplicates (can't really occur...)
289  if (id)
290  {
291  j=i;
292  while ((pInfo2 = pNewInfo->GetPlayerInfo(++j)))
293  if (pInfo2->GetAssociatedSavegamePlayerID() == id)
294  {
295  // fix it by resetting the savegame info
296  pInfo->SetAssociatedSavegamePlayer(id=0);
297  pNewInfo->SetUpdated(); break;
298  }
299  }
300  // check against all infos of other clients
301  C4ClientPlayerInfos *pkClientInfo; int k=0;
302  while ((pkClientInfo = rInfoList.GetIndexedInfo(k++)) && id)
303  {
304  // if it's not an add packet, don't check own client twice
305  if (pkClientInfo->GetClientID() == pNewInfo->GetClientID() && !(pNewInfo->IsAddPacket()))
306  continue;
307  // check against all players
308  j=0;
309  while ((pInfo2 = pkClientInfo->GetPlayerInfo(j++)))
310  if (pInfo2->GetAssociatedSavegamePlayerID() == id)
311  {
312  // fix it by resetting the savegame info
313  pInfo->SetAssociatedSavegamePlayer(id=0);
314  pNewInfo->SetUpdated(); break;
315  }
316  }
317  // if the player joined just for the savegame assignment, and that failed, delete it
318  if (!id && pInfo->IsJoinForSavegameOnly())
319  pNewInfo->RemoveIndexedInfo(i);
320  // prev info
321  }
322 }
323 
325 {
326  // mark all client packets as up-to-date
327  C4ClientPlayerInfos *pUpdInfo; int i=0;
328  while ((pUpdInfo = rInfoList.GetIndexedInfo(i++))) pUpdInfo->ResetUpdated();
329 }
330 
331 void C4Network2Players::JoinUnjoinedPlayersInControlQueue(C4ClientPlayerInfos *pNewPacket)
332 {
333  // only host may join any players to the queue
334  assert(::Network.isHost());
335  // check all players
336  int i=0; C4PlayerInfo *pInfo;
337  while ((pInfo = pNewPacket->GetPlayerInfo(i++)))
338  // not yet joined and no savegame assignment?
339  if (!pInfo->HasJoinIssued()) if (!pInfo->GetAssociatedSavegamePlayerID())
340  {
341  // join will be marked when queue is executed (C4Player::Join)
342  // but better mark join now already to prevent permanent sending overkill
343  pInfo->SetJoinIssued();
344  // do so!
345  C4Network2Res *pPlrRes = pInfo->GetRes();
346  C4Network2Client *pClient = ::Network.Clients.GetClientByID(pNewPacket->GetClientID());
347  if (!pPlrRes || (!pClient && pNewPacket->GetClientID() != ::Control.ClientID()))
348  if (pInfo->GetType() != C4PT_Script)
349  {
350  // failure: Non-script players must have a res to join from!
351  const char *szPlrName = pInfo->GetName(); if (!szPlrName) szPlrName="???";
352  LogF("Network: C4Network2Players::JoinUnjoinedPlayersInControlQueue failed to join player %s!", szPlrName);
353  continue;
354  }
355  if (pPlrRes)
356  {
357  // join with resource
359  new C4ControlJoinPlayer(pPlrRes->getFile(), pNewPacket->GetClientID(), pInfo->GetID(), pPlrRes->getCore()));
360  }
361  else
362  {
363  // join without resource (script player)
365  new C4ControlJoinPlayer(nullptr, pNewPacket->GetClientID(), pInfo->GetID()));
366  }
367  }
368 }
369 
370 void C4Network2Players::HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn)
371 {
372  if (!pConn) return;
373 
374  // find associated client
375  C4Network2Client *pClient = ::Network.Clients.GetClient(pConn);
376  if (!pClient) pClient = ::Network.Clients.GetClientByID(pConn->getClientID());
377 
378 #define GETPKT(type, name) \
379  assert(pPacket); const type &name = \
380  static_cast<const type &>(*pPacket);
381 
382  // player join request?
383  if (cStatus == PID_PlayerInfoUpdReq)
384  {
386  // this packet is sent to the host only, and thus cannot have been sent from the host
387  if (!::Network.isHost()) return;
388  // handle this packet
389  HandlePlayerInfoUpdRequest(&pkPlrInfo.Info, false);
390  }
391  else if (cStatus == PID_LeagueRoundResults)
392  {
393  GETPKT(C4PacketLeagueRoundResults, pkLeagueInfo);
394  // accepted from the host only
395  if (!pClient || !pClient->isHost()) return;
396  // process
397  Game.RoundResults.EvaluateLeague(pkLeagueInfo.sResultsString.getData(), pkLeagueInfo.fSuccess, pkLeagueInfo.Players);
398  }
399 
400 #undef GETPKT
401 }
402 
404 {
405  // lobby could be notified about the removal - but this would be redundant, because
406  // client leave notification is already done directly; this will delete any associated players
407  C4ClientPlayerInfos **ppCltInfo = rInfoList.GetInfoPtrByClientID(pPartClient->getID());
408  // abort here if no info is registered - client seems to have had a short life only, anyway...
409  if (!ppCltInfo) return;
410  // remove all unjoined player infos
411  for (int32_t i = 0; i < (*ppCltInfo)->GetPlayerCount();)
412  {
413  C4PlayerInfo *pInfo = (*ppCltInfo)->GetPlayerInfo(i);
414  // not joined yet? remove it
415  if (!pInfo->HasJoined())
416  (*ppCltInfo)->RemoveIndexedInfo(i);
417  else
418  // just ignore, the "removed" flag will be set eventually
419  i++;
420  }
421  // empty? remove
422  if (!(*ppCltInfo)->GetPlayerCount())
423  rInfoList.RemoveInfo(ppCltInfo);
424  // update team association to left player
426  // host: update player data according to leaver
427  if (::Network.isHost() && ::Network.isEnabled())
428  {
429  // host: update any player colors and names
430  rInfoList.UpdatePlayerAttributes();
431  // team distribution of remaining unjoined players may change
433  // league score gains may now be different
435  // send changes to all clients and reset update flags
437  }
438  // invalidate reference
439  if (::Network.isHost())
441 }
442 
444 {
445  // host only
446  if (!::Network.isHost()) return;
447  // check all player lists
448  int i=0; C4ClientPlayerInfos *pkInfo;
449  while ((pkInfo = rInfoList.GetIndexedInfo(i++)))
450  // any unsent player joins?
451  if (pkInfo->HasUnjoinedPlayers())
452  {
453  // get client core
454  const C4Client *pClient = Game.Clients.getClientByID(pkInfo->GetClientID());
455  // don't send if client is unknown or not activated yet
456  if (!pClient || !pClient->isActivated()) continue;
457  // send them w/o info packet
458  // info packets are synced during pause mode
459  JoinUnjoinedPlayersInControlQueue(pkInfo);
460  }
461 }
462 
464 {
465  // get local client ID
466  int iLocalClientID = Game.Clients.getLocalID();
467  // check all packets for same client ID as local
468  int i=0; C4ClientPlayerInfos *pkInfo;
469  while ((pkInfo = rInfoList.GetIndexedInfo(i++)))
470  if (pkInfo->GetClientID() == iLocalClientID)
471  // found
472  return pkInfo;
473  // not found
474  return nullptr;
475 }
476 
478 {
479  // just get from info list
480  return rInfoList.GetIndexedInfo(iIndex);
481 }
482 
483 DWORD C4Network2Players::GetClientChatColor(int idForClient, bool fLobby) const
484 {
485  // return color of first joined player; force to white for unknown
486  // deactivated always white
487  const C4Client *pClient = Game.Clients.getClientByID(idForClient);
488  if (pClient && pClient->isActivated())
489  {
490  // get players for activated
491  C4ClientPlayerInfos *pInfoPacket = rInfoList.GetInfoByClientID(idForClient);
492  C4PlayerInfo *pPlrInfo;
493  if (pInfoPacket && (pPlrInfo = pInfoPacket->GetPlayerInfo(0, C4PT_User)))
494  {
495  if (fLobby)
496  return pPlrInfo->GetLobbyColor();
497  else
498  return pPlrInfo->GetColor();
499  }
500  }
501  // default color
502  return 0xffffff;
503 }
504 
void RecheckTeams()
Definition: C4Teams.cpp:670
C4Client * getLocal() const
Definition: C4Client.h:161
void RecheckPlayers()
Definition: C4Teams.cpp:664
class C4GameLobby::MainDlg * GetLobby() const
Definition: C4Network2.h:216
C4Network2Res * GetRes() const
Definition: C4PlayerInfo.h:166
bool IsRunning
Definition: C4Game.h:141
C4PlayerInfoList & RestorePlayerInfos
Definition: C4Game.h:74
bool SendMsgToHost(C4NetIOPacket rPkt)
const char * GetName() const
Definition: C4PlayerInfo.h:160
C4Network2Client * GetClientByID(int32_t iID) const
bool isHost() const
Definition: C4Network2.h:209
bool isRunning() const
Definition: C4Network2.h:206
bool LeaguePlrAuthCheck(C4PlayerInfo *pInfo)
void RequestPlayerInfoUpdate(const class C4ClientPlayerInfos &rRequest)
C4Game Game
Definition: C4Globals.cpp:52
bool IsJoinForSavegameOnly()
Definition: C4PlayerInfo.h:133
C4Scenario C4S
Definition: C4Game.h:76
C4PlayerInfo * GetPlayerInfoByRes(int32_t idResID) const
bool isLobbyActive() const
Definition: C4Network2.h:204
void SetAuthID(const char *sznAuthID)
Definition: C4PlayerInfo.h:136
bool Replay
Definition: C4Scenario.h:72
void RemoveInfo(C4ClientPlayerInfos **ppRemoveInfo)
Definition: C4PlayerInfo.h:389
uint32_t GetLobbyColor() const
C4ClientPlayerInfos * GetLocalPlayerInfoPacket() const
bool isActivated() const
Definition: C4Client.h:110
void Add(C4PacketType eType, C4ControlPacket *pCtrl)
Definition: C4Control.h:82
C4Network2Client * GetClient(const char *szName) const
C4ClientPlayerInfos ** GetInfoPtrByClientID(int32_t iClientID) const
void UpdatePlayerAttributes(C4ClientPlayerInfos *pForInfo, bool fResolveConflicts)
C4GameParameters & Parameters
Definition: C4Game.h:69
C4ClientPlayerInfos * GetIndexedInfo(int32_t iIndex) const
Definition: C4PlayerInfo.h:361
C4PlayerInfo * GetPlayerInfoByID(int32_t id) const
C4TeamList & Teams
Definition: C4Game.h:72
void AssignTeams(C4ClientPlayerInfos *pNewClientInfo, bool fByHost)
void HandlePacket(char cStatus, const C4PacketBase *pPacket, class C4Network2IOConnection *pConn)
int32_t getID() const
Definition: C4Client.h:105
bool IsAddPacket() const
Definition: C4PlayerInfo.h:263
const char * getFile() const
C4PlayerInfo * GetPlayerInfo(int32_t iIndex) const
bool isObserver() const
Definition: C4Client.h:111
C4Network2 Network
Definition: C4Globals.cpp:53
const C4Network2ResCore & getCore() const
int32_t GetAssociatedSavegamePlayerID() const
Definition: C4PlayerInfo.h:129
DWORD GetClientChatColor(int idForClient, bool fLobby) const
int iCnt
Definition: TstC4NetIO.cpp:35
int32_t getLocalID() const
Definition: C4Client.h:171
C4ClientPlayerInfos * AddInfo(C4ClientPlayerInfos *pNewClientInfo)
void InvalidateReference()
C4GameControl Control
C4NetIOPacket MkC4NetIOPacket(char cStatus, const class C4PacketBase &Pkt, const C4NetIO::addr_t &addr=C4NetIO::addr_t())
Definition: C4PacketBase.h:40
int getClientID() const
Definition: C4Network2IO.h:271
int32_t GetClientID() const
Definition: C4PlayerInfo.h:260
void DoInput(C4PacketType eCtrlType, C4ControlPacket *pPkt, C4ControlDeliveryType eDelivery)
int32_t GetPlayerCount() const
Definition: C4PlayerInfo.h:254
bool LeaguePlrAuth(C4PlayerInfo *pInfo)
bool HasJoinIssued() const
Definition: C4PlayerInfo.h:170
C4ClientPlayerInfos Info
Definition: C4PlayerInfo.h:280
bool isEnabled() const
Definition: C4Network2.h:203
C4RoundResults & RoundResults
Definition: C4Game.h:75
C4ClientPlayerInfos * GetInfoByClientID(int32_t iClientID) const
Definition: C4PlayerInfo.h:364
C4Control & Input
Definition: C4Game.h:84
void EvaluateLeague(const char *szResultMsg, bool fSuccess, const C4RoundResultsPlayers &rLeagueInfo)
void SetJoinIssued()
Definition: C4PlayerInfo.h:115
uint32_t GetColor() const
Definition: C4PlayerInfo.h:156
C4Network2ClientList Clients
Definition: C4Network2.h:116
C4PlayerInfoList & PlayerInfos
Definition: C4Game.h:73
char PlayerFilenames[20 *_MAX_PATH+1]
Definition: C4Game.h:106
C4Client * getClientByID(int32_t iID) const
Definition: C4Client.cpp:217
int32_t ClientID() const
bool Log(const char *szMessage)
Definition: C4Log.cpp:195
C4ClientList & Clients
Definition: C4Game.h:71
bool isLeague() const
void OnClientPart(class C4Client *pPartClient)
void SetAssociatedSavegamePlayer(int32_t aidSavegamePlayer)
Definition: C4PlayerInfo.h:127
void RemoveIndexedInfo(int32_t iAtIndex)
bool HasUnjoinedPlayers() const
int32_t GetID() const
Definition: C4PlayerInfo.h:197
C4PlayerType GetType() const
Definition: C4PlayerInfo.h:155
C4SHead Head
Definition: C4Scenario.h:230
bool JoinLocalPlayer(const char *szLocalPlayerFilename, bool initial=false)
void RequestActivate()
uint32_t DWORD
bool AssignPlayerIDs(C4ClientPlayerInfos *pNewClientInfo)
void ResetLeagueProjectedGain(bool fSetUpdated)
void ResetLeagueProjectedGain()
Definition: C4PlayerInfo.h:148
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:253
void HandlePlayerInfoUpdRequest(const class C4ClientPlayerInfos *pInfoPacket, bool fByHost)
bool HasJoined() const
Definition: C4PlayerInfo.h:168
void CreateRestoreInfosForJoinedScriptPlayers(C4PlayerInfoList &rSavegamePlayers)
void HandlePlayerInfo(const class C4ClientPlayerInfos &rInfoPacket)
#define GETPKT(type, name)
int32_t getResID() const
bool isHost() const
C4ClientPlayerInfos * GetIndexedPlayerInfoPacket(int iIndex)