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 // permanent player information management 17 // 18 // A separate list of all local and remote player infos is held here, 19 // independantely of the global C4PlayerList. 20 // This list is used for: 21 // -player information to be known before actual join 22 // (player count for landscape width, team, color, etc.) 23 // -player file resource association (network mode) 24 // -league information to be stored for each player; even after elimination 25 // *-startup loader screen information; e.g. for replays 26 // 27 // * = 2do 28 // 29 // Please note that any fields added to C4PlayerInfo will be transferred to the masterserver and back. 30 // C4RoundResults is responsible for collecting information after player elimination. 31 32 #ifndef INC_C4PlayerInfo 33 #define INC_C4PlayerInfo 34 35 #include "config/C4Constants.h" 36 #include "lib/C4InputValidation.h" 37 #include "network/C4PacketBase.h" 38 #include "network/C4Network2Res.h" 39 #include "object/C4Id.h" 40 41 // information about one player at a client 42 class C4PlayerInfo 43 { 44 public: 45 // player flags 46 enum Flags 47 { 48 PIF_Joined = 1 << 0, // player has joined the game 49 PIF_Removed = 1 << 2, // player has been removed 50 PIF_HasRes = 1 << 3, // pRes is set 51 PIF_JoinIssued = 1 << 4, // flag for host to mark a player for which the join is issued 52 PIF_TempFile = 1 << 5, // player file is temporary and to be deleted after join recreation 53 PIF_InScenarioFile = 1 << 6, // player file is present within the scenario; res is not to be used 54 PIF_JoinedForSavegameOnly = 1 << 7, // player file has been specified to take over a savegame player; do not join as normal player if association fails 55 PIF_Disconnected = 1 << 8, // the player was removed because his client disconnected 56 PIF_Won = 1 << 9, // player survived until game end (for game evaluation only) 57 PIF_VotedOut = 1 << 10, // player was removed from the round after a successful voting 58 PIF_AttributesFixed = 1 << 11, // player color and name aren't changed on collision 59 PIF_NoScenarioInit = 1 << 12, // do not call ScenariInit for this player 60 PIF_NoEliminationCheck = 1 << 13, // do not eliminate player if crew is empty 61 PIF_Invisible = 1 << 14, // do not show in lobby and menus 62 PIF_NoScenarioSave = 1 << 15, // not saved in SavePlayerInfos.txt if "save as scenario" is performed 63 64 // flags to be synchronized via network and saved into player info 65 PIF_SyncFlags = PIF_Joined | PIF_Removed | PIF_HasRes | PIF_InScenarioFile | PIF_JoinedForSavegameOnly | PIF_Disconnected | PIF_Won | PIF_VotedOut | PIF_AttributesFixed | PIF_NoScenarioInit | PIF_NoEliminationCheck | PIF_Invisible | PIF_NoScenarioSave, 66 67 // flags to be copied from savegame-player for takeover 68 PIF_SavegameTakeoverFlags = PIF_Joined | PIF_Removed | PIF_JoinIssued | PIF_AttributesFixed | PIF_NoScenarioInit | PIF_NoEliminationCheck | PIF_Invisible | PIF_NoScenarioSave, 69 }; 70 71 // player attributes used in attribute conflict resolver 72 enum Attribute { PLRATT_Color=0, PLRATT_Name=1, PLRATT_Last=2 }; 73 enum AttributeLevel { PLRAL_Current, PLRAL_Original, PLRAL_Alternate }; 74 private: 75 uint32_t dwFlags{0}; // DWORD-mask of C4PlayerInfoFlags-constants 76 C4PlayerType eType{C4PT_User}; // user or script player 77 78 ValidatedStdCopyStrBuf<C4InVal::VAL_NameNoEmpty> sName; // player name 79 ValidatedStdCopyStrBuf<C4InVal::VAL_NameAllowEmpty> sForcedName; // player name if a new name is forced e.g. because the current name appeared twice 80 int32_t iID{0}; // unique ID set by host 81 C4Network2Res::Ref pRes; // player resource to load from 82 C4Network2ResCore ResCore; // core of resource to load from 83 StdCopyStrBuf szFilename; // source filename for local players 84 uint32_t dwColor{0xffffffff}; // player color 85 uint32_t dwOriginalColor{0}, dwAlternateColor{0}; // original player color wish 86 int32_t idSavegamePlayer{0}; // ID of associated savegame player 87 int32_t idTeam{0}; // team ID 88 StdCopyStrBuf szAuthID; // authentication ID (for league server, will be cleared on successful join) 89 int32_t iInGameNumber{-1}, iInGameJoinFrame{-1}, iInGamePartFrame{-1}; // information about player in game 90 C4ID idExtraData; // extra data for script players 91 92 ValidatedStdCopyStrBuf<C4InVal::VAL_NameAllowEmpty> sLeagueAccount; // account name on league server 93 int32_t iLeagueScore{0}; // score on league server at join time 94 int32_t iLeagueRank{0}; // rank on league server at join time 95 int32_t iLeagueRankSymbol{0}; // symbolization of the player's rank 96 int32_t iLeagueScoreProjected;// score on league server in case of win 97 int32_t iLeagueProjectedGain{-1}; // projected league score increase if game is won - -1 for unknown; valid values always positive 98 ValidatedStdCopyStrBuf<C4InVal::VAL_NameAllowEmpty> sClanTag; // clan ("team") tag 99 int32_t iLeaguePerformance{0}; // script-set league performance value, only set temporarily for masterserver end reference 100 StdCopyStrBuf sLeagueProgressData; // level progress data as reported by league 101 102 public: C4PlayerInfo()103 C4PlayerInfo() // construct empty 104 : pRes(nullptr), szFilename(), idExtraData(C4ID::None), sLeagueAccount("") { } 105 106 void Clear(); // clear fields 107 108 bool LoadFromLocalFile(const char *szFilename); // load data from local file 109 bool SetAsScriptPlayer(const char *szName, uint32_t dwColor, uint32_t dwFlags, C4ID idExtra); // set as a script (AI) player 110 111 void SetJoined(int32_t iNumber); // mark as joined in current game frame SetJoinIssued()112 void SetJoinIssued() { dwFlags |= PIF_JoinIssued; } // mark as joined 113 void SetRemoved(); // mark as removed in current game frame - always marks as previously joined, too SetID(int32_t iToID)114 void SetID(int32_t iToID) { iID = iToID; } // set player info ID SetColor(DWORD dwUseClr)115 void SetColor(DWORD dwUseClr) { dwColor = dwUseClr; } // set color to be used SetOriginalColor(DWORD dwUseClr)116 void SetOriginalColor(DWORD dwUseClr) { dwOriginalColor = dwUseClr; } // set color the player wishes to have 117 void SetFilename(const char *szToFilename); // set new player filename 118 void SetToScenarioFilename(const char *szScenFilename); // set to file within scenario; discard resource SetTempFile()119 void SetTempFile() { assert(!!szFilename); dwFlags |= PIF_TempFile; } // mark filename as temp, so it is deleted in dtor or after join SetTeam(int32_t idToTeam)120 void SetTeam(int32_t idToTeam) { idTeam = idToTeam; } 121 void DeleteTempFile(); // delete filename if temp 122 void LoadResource(); // network: Load resource if present and not being loaded yet 123 void DiscardResource(); // delete any source resource for network player infos SetAssociatedSavegamePlayer(int32_t aidSavegamePlayer)124 void SetAssociatedSavegamePlayer(int32_t aidSavegamePlayer) // link with savegame player from restore list 125 { idSavegamePlayer=aidSavegamePlayer; } GetAssociatedSavegamePlayerID()126 int32_t GetAssociatedSavegamePlayerID() const 127 { return idSavegamePlayer; } SetJoinForSavegameOnly()128 void SetJoinForSavegameOnly() // flag to be deleted if savegame association fails 129 { dwFlags |= PIF_JoinedForSavegameOnly; } IsJoinForSavegameOnly()130 bool IsJoinForSavegameOnly() // flag to be deleted if savegame association fails 131 { return !!(dwFlags & PIF_JoinedForSavegameOnly); } 132 bool SetSavegameResume(C4PlayerInfo *pSavegameInfo); // take over savegame player data to do resume SetAuthID(const char * sznAuthID)133 void SetAuthID(const char *sznAuthID) 134 { szAuthID = sznAuthID; } SetLeagueData(const char * szAccount,const char * szNewClanTag,int32_t iScore,int32_t iRank,int32_t iRankSymbol,const char * szProgressData)135 void SetLeagueData(const char *szAccount, const char *szNewClanTag, int32_t iScore, int32_t iRank, int32_t iRankSymbol, const char *szProgressData) 136 { sLeagueAccount.CopyValidated(szAccount); sClanTag.CopyValidated(szNewClanTag); iLeagueScore = iScore; iLeagueRank = iRank; iLeagueRankSymbol = iRankSymbol; sLeagueProgressData.Copy(szProgressData); } SetLeaguePerformance(int32_t iNewPerf)137 void SetLeaguePerformance(int32_t iNewPerf) 138 { iLeaguePerformance = iNewPerf; } SetLeagueProgressData(const char * szNewProgressData)139 void SetLeagueProgressData(const char *szNewProgressData) 140 { if (szNewProgressData) sLeagueProgressData.Copy(szNewProgressData); else sLeagueProgressData.Clear(); } SetVotedOut()141 void SetVotedOut() 142 { dwFlags |= PIF_VotedOut; } SetLeagueProjectedGain(int32_t iProjectedGain)143 void SetLeagueProjectedGain(int32_t iProjectedGain) 144 { assert(iProjectedGain>=0); iLeagueProjectedGain = iProjectedGain; } ResetLeagueProjectedGain()145 void ResetLeagueProjectedGain() 146 { iLeagueProjectedGain = -1; } SetForcedName(const char * szNewName)147 void SetForcedName(const char *szNewName) 148 { if (szNewName) sForcedName.CopyValidated(szNewName); else sForcedName.Clear(); } 149 150 void CompileFunc(StdCompiler *pComp); 151 GetType()152 C4PlayerType GetType() const { return eType; } GetColor()153 uint32_t GetColor() const { return dwColor; } // get player color 154 uint32_t GetLobbyColor() const; GetOriginalColor()155 uint32_t GetOriginalColor() const { return dwOriginalColor; } // get original player color GetAlternateColor()156 uint32_t GetAlternateColor() const { return dwAlternateColor; } // get secondary original player color GetName()157 const char *GetName() const { return sLeagueAccount.getLength() ? sLeagueAccount.getData() : sForcedName.getLength() ? sForcedName.getData() : sName.getData(); } // get player name GetOriginalName()158 const char *GetOriginalName() const { return sName.getData(); } GetForcedName()159 const char *GetForcedName() const { return sForcedName.getData(); } 160 StdStrBuf GetLobbyName() const; // return player name including clan/team tag if known; fallback to regular player name GetFilename()161 const char *GetFilename() const { return szFilename.getData(); } // get filename for local games 162 const char *GetLocalJoinFilename() const; // get name of file to join the player from GetRes()163 C4Network2Res *GetRes() const { return pRes; } // get player resource for network games IsRemoved()164 bool IsRemoved() const { return !!(dwFlags & PIF_Removed); } HasJoined()165 bool HasJoined() const { return !!(dwFlags & PIF_Joined); } // return whether player has joined IsJoined()166 bool IsJoined() const { return HasJoined() && !(dwFlags & PIF_Removed); } // return whether player is currently in the game HasJoinIssued()167 bool HasJoinIssued() const { return !!(dwFlags & (PIF_Joined | PIF_JoinIssued)); } // return whether player join is in the queue already (or performed long ago, even) HasJoinPending()168 bool HasJoinPending() const { return !(dwFlags & (PIF_Joined | PIF_Removed)); } // return whether player join should be done but has not been performed yet IsUsingColor()169 bool IsUsingColor() const { return !IsRemoved() && !idSavegamePlayer; } //return whether the player is actually using the player color IsUsingName()170 bool IsUsingName() const { return !IsRemoved() && !sLeagueAccount.getLength(); } //return whether the player is actually using the player name (e.g. not if league name is used) IsUsingAttribute(Attribute eAttr)171 bool IsUsingAttribute(Attribute eAttr) const { if (eAttr == PLRATT_Color) return IsUsingColor(); else return IsUsingName(); } IsUsingPlayerFile()172 bool IsUsingPlayerFile() const { return !IsRemoved(); } //return whether the player is using the file (i.e., isn't dead yet) IsUsingTeam()173 bool IsUsingTeam() const { return !IsRemoved(); } // whether player should be in the team list IsAttributesFixed()174 bool IsAttributesFixed() const { return !!(dwFlags & PIF_AttributesFixed); } IsInvisible()175 bool IsInvisible() const { return !!(dwFlags & PIF_Invisible); } IsScenarioInitDesired()176 bool IsScenarioInitDesired() const { return !(dwFlags & PIF_NoScenarioInit); } IsScenarioSaveDesired()177 bool IsScenarioSaveDesired() const { return !(dwFlags & PIF_NoScenarioSave); } GetScriptPlayerExtraID()178 C4ID GetScriptPlayerExtraID() const { return idExtraData; } IsNoEliminationCheck()179 bool IsNoEliminationCheck() const { return !!(dwFlags & PIF_NoEliminationCheck); } HasAutoGeneratedColor()180 bool HasAutoGeneratedColor() { return dwColor != dwOriginalColor; } // whether the player got a new color assigned due to color conflict HasWon()181 bool HasWon() const { return !!(dwFlags & PIF_Won); } 182 bool HasTeamWon() const; getAuthID()183 const char *getAuthID() const { return szAuthID.getData(); } // returns authentication ID for this player [league] getLeagueAccount()184 const char *getLeagueAccount() const { return sLeagueAccount.getData(); } // returns account name on league server getLeagueScore()185 int32_t getLeagueScore() const { return iLeagueScore; } // returns score number on league server (0 for not assigned) getLeagueRank()186 int32_t getLeagueRank() const { return iLeagueRank; } // returns rank on league server (0 for not assigned) getLeagueRankSymbol()187 int32_t getLeagueRankSymbol() const { return iLeagueRankSymbol; } // returns rank symbol on league server (0 for not assigned) getLeagueScoreProjected()188 int32_t getLeagueScoreProjected() const { return iLeagueScoreProjected; } // returns score on league server in case of win (0 for not assigned) GetInGameNumber()189 int32_t GetInGameNumber() const { return iInGameNumber; } // returns player number the player had in the game IsLeagueProjectedGainValid()190 bool IsLeagueProjectedGainValid() const { return iLeagueProjectedGain>=0; } GetLeagueProjectedGain()191 int32_t GetLeagueProjectedGain() const { return iLeagueProjectedGain; } // get score gain in primary league if this player's team wins GetLeagueProgressData()192 const char *GetLeagueProgressData() const { return sLeagueProgressData.getData(); } 193 GetID()194 int32_t GetID() const { return iID; } // get unique ID, if assigned GetTeam()195 int32_t GetTeam() const { return idTeam; } IsTempFile()196 bool IsTempFile() const { return !!(dwFlags & PIF_TempFile); } // return whether filename points to temp folder 197 GetFlags()198 DWORD GetFlags() { return dwFlags; } // for dbg print only 199 SetDisconnected()200 void SetDisconnected() { dwFlags |= PIF_Disconnected; } SetWinner()201 void SetWinner() { dwFlags |= PIF_Won; } 202 203 bool LoadBigIcon(C4FacetSurface &fctTarget); // load BigIcon.png of player into target facet; return false if no bigicon present or player file not yet loaded 204 }; 205 206 // player infos for one client 207 // merely a list of player infos 208 class C4ClientPlayerInfos 209 { 210 private: 211 // std::vector... 212 int32_t iPlayerCount{0}; // number of clients registered into the list 213 int32_t iPlayerCapacity{0}; // size of pClients-array 214 C4PlayerInfo **ppPlayers{nullptr}; // array of registered client information 215 void GrowList(size_t iByVal); // increase list capacity 216 217 int32_t iClientID{-1}; // ID of client described by this packet 218 219 // flags for this packet 220 enum Flags 221 { 222 CIF_AddPlayers = 1<<0, // if set, the players are to be added to the current list (otherwise overwrite) 223 CIF_Updated = 1<<1, // set temporarily if changed and not transmissioned to clients (valid for host only) 224 CIF_Initial = 1<<2, // set for first-time player info packets 225 CIF_Developer = 1<<3, // set for developer hosts (by regkey); client side check only! 226 CIF_Removed = 1<<4 // client was removed 227 }; 228 uint32_t dwFlags{0}; // bit mask of the above flags 229 230 public: 231 C4ClientPlayerInfos(const char *szJoinFilenames=nullptr, bool fAdd=false, C4PlayerInfo *pAddInfo=nullptr); // ctor; sets local data (or makes an add-player-packet if filename is given) if par is true 232 C4ClientPlayerInfos(const C4ClientPlayerInfos &rCopy); // copy ctor ~C4ClientPlayerInfos()233 ~C4ClientPlayerInfos() { Clear(); } // dtor 234 235 C4ClientPlayerInfos &operator = (const C4ClientPlayerInfos &rCopy); 236 237 void Clear(); // del all players 238 void GrabMergeFrom(C4ClientPlayerInfos &rFrom); // merge existing player info packed into this one - empties pFrom! 239 void AddInfo(C4PlayerInfo *pAddInfo); // add info to list 240 void RemoveIndexedInfo(int32_t iAtIndex); // remove info from list (delete it) 241 void RemoveInfo(int32_t idPlr); // remove info from list (delete it) 242 243 // update-flag SetUpdated()244 void SetUpdated() { dwFlags |= CIF_Updated; } IsUpdated()245 bool IsUpdated() { return !!(dwFlags & CIF_Updated); } ResetUpdated()246 void ResetUpdated() { dwFlags &= ~CIF_Updated; } SetAdd()247 void SetAdd() { dwFlags |= CIF_AddPlayers; } ResetAdd()248 void ResetAdd() { dwFlags &= ~CIF_AddPlayers; } 249 250 // query functions GetPlayerCount()251 int32_t GetPlayerCount() const { return iPlayerCount; } // get number of player infos available 252 int32_t GetFlaggedPlayerCount(DWORD dwFlag) const; // get number of player infos with any of the given flags set 253 C4PlayerInfo *GetPlayerInfo(int32_t iIndex) const; // get indexed player info 254 C4PlayerInfo *GetPlayerInfo(int32_t iIndex, C4PlayerType eType) const; // get indexed player info of given type 255 C4PlayerInfo *GetPlayerInfoByID(int32_t id) const; // get player info by unique player ID 256 C4PlayerInfo *GetPlayerInfoByRes(int32_t idResID) const; // get player info by resource ID GetClientID()257 int32_t GetClientID() const { return iClientID; } // get target client ID 258 bool HasUnjoinedPlayers() const; // check all players and return whether one of them didn't join 259 int32_t GetJoinedPlayerCount() const; // return number of players that are IsJoined() IsAddPacket()260 bool IsAddPacket() const { return !!(dwFlags & CIF_AddPlayers); } // return whether players are to be added to the current list (otherwise overwrite) IsInitialPacket()261 bool IsInitialPacket() const { return !!(dwFlags & CIF_Initial); } // returns whether this packet was sent as the first local-join packet IsDeveloperPacket()262 bool IsDeveloperPacket() const { return !!(dwFlags & CIF_Developer); } // returns whether packet was created by a developer host - client side check only! 263 264 // network: Load all resources connected with the players that are not being loaded yet 265 void LoadResources(); 266 267 // pack/unpack functions 268 void CompileFunc(StdCompiler *pComp); 269 }; 270 271 // * PID_PlayerInfoUpdRequest 272 // packet containing information about one or more joined players at a client 273 // or about lobby player-info updates 274 class C4PacketPlayerInfoUpdRequest : public C4PacketBase 275 { 276 public: 277 C4ClientPlayerInfos Info; // info for clients to be joined 278 C4PacketPlayerInfoUpdRequest()279 C4PacketPlayerInfoUpdRequest() : Info() { } // std ctor C4PacketPlayerInfoUpdRequest(const char * szFilenames,bool fAdd)280 C4PacketPlayerInfoUpdRequest(const char *szFilenames, bool fAdd) // ctor 281 : Info(szFilenames, fAdd) { }; 282 C4PacketPlayerInfoUpdRequest(const C4ClientPlayerInfos & rInfo)283 C4PacketPlayerInfoUpdRequest(const C4ClientPlayerInfos &rInfo) : Info(rInfo) {} // ctor 284 285 void CompileFunc(StdCompiler *pComp) override; 286 }; 287 288 // * PID_PlayerInfoUpd 289 // packet containing information about one or more (updated) players at a client 290 class C4PacketPlayerInfo : public C4PacketBase 291 { 292 public: 293 C4ClientPlayerInfos Info; // info for clients to be updated 294 bool fIsRecreationInfo{false}; // if set, this info packet describes savegame recreation players 295 C4PacketPlayerInfo()296 C4PacketPlayerInfo() : Info() { } // std ctor C4PacketPlayerInfo(const C4ClientPlayerInfos & rCopyInfos,bool fRecreationPlayers)297 C4PacketPlayerInfo(const C4ClientPlayerInfos &rCopyInfos, bool fRecreationPlayers) // ctor 298 : Info(rCopyInfos), fIsRecreationInfo(fRecreationPlayers) { }; 299 300 void CompileFunc(StdCompiler *pComp) override; 301 }; 302 303 // player info list 304 // contains player info packets for all known clients and self 305 class C4PlayerInfoList 306 { 307 private: 308 // std::vector... 309 int32_t iClientCount{0}; // number of clients registered into the list 310 int32_t iClientCapacity{0}; // size of pClients-array 311 C4ClientPlayerInfos **ppClients{nullptr}; // array of registered client information 312 void GrowList(size_t iByVal); // increase list capacity 313 314 int32_t iLastPlayerID{0}; // last ID given to a player 315 316 enum MatchingLevel { PML_PlrFileName=0, PML_PlrName, PML_PrefColor, PML_Any }; 317 318 public: 319 C4PlayerInfoList(); // ctor 320 C4PlayerInfoList(const C4PlayerInfoList &rCpy); ~C4PlayerInfoList()321 ~C4PlayerInfoList() { Clear(); } // dtor 322 C4PlayerInfoList &operator = (const C4PlayerInfoList &rCpy); 323 void Clear(); // clear list 324 325 // forwards player info update request to the appropriate handler 326 bool DoPlayerInfoUpdate(C4ClientPlayerInfos *pUpdate); 327 328 // performs a local player join for the given player file(s) 329 bool DoLocalNonNetworkPlayerJoin(const char *szPlayerFile); 330 bool DoLocalNonNetworkPlayerInfoUpdate(C4ClientPlayerInfos *pUpdate); 331 332 // sets any unset IDs (host/standalone only); also removes players that would exceed the maximum player limit 333 // returns whether any players remain 334 bool AssignPlayerIDs(C4ClientPlayerInfos *pNewClientInfo); 335 336 // assign any unset teams (host/standalone only) - fByHost determines whether packet was sent by host 337 void AssignTeams(C4ClientPlayerInfos *pNewClientInfo, bool fByHost); 338 339 // generate teams used by the player info list if they do not exist and auto generated teams are enabled 340 // used for replays 341 void RecheckAutoGeneratedTeams(); 342 343 // add info for client; overwriting or appending to existing info if necessary 344 // this takes over the pNewClientInfo ptr, and may invalidate (delete) it! 345 // the pointer to the info structure as it is valid in the list is returned 346 // when infos are added, unset IDs will automatically be assigned (should happen for host only!) 347 C4ClientPlayerInfos *AddInfo(C4ClientPlayerInfos *pNewClientInfo); 348 349 // resolve any color conflicts in self AND given (optional) packet. Sets Updated-flags. 350 void ResolvePlayerAttributeConflicts(C4ClientPlayerInfos *pSecPacket); 351 352 // do color updates: Savegame color assignment; team colors; duplicate attribute check 353 void UpdatePlayerAttributes(C4ClientPlayerInfos *pForInfo, bool fResolveConflicts); 354 void UpdatePlayerAttributes(); 355 356 // query functions GetInfoCount()357 int32_t GetInfoCount() const { return iClientCount; } // get number of registered client infos GetIndexedInfo(int32_t iIndex)358 C4ClientPlayerInfos *GetIndexedInfo(int32_t iIndex) const // get client player infos by indexed 359 { return (ppClients && Inside<int32_t>(iIndex, 0, iClientCount-1)) ? ppClients[iIndex] : nullptr; } 360 C4ClientPlayerInfos **GetInfoPtrByClientID(int32_t iClientID) const; // get info for a specific client ID GetInfoByClientID(int32_t iClientID)361 C4ClientPlayerInfos *GetInfoByClientID(int32_t iClientID) const 362 { C4ClientPlayerInfos **ppNfo = GetInfoPtrByClientID(iClientID); return ppNfo ? *ppNfo : nullptr; } 363 C4PlayerInfo *GetPlayerInfoByIndex(int32_t index) const; // get player info by index (for running through all players regardless of clients or ids) 364 C4PlayerInfo *GetPlayerInfoByID(int32_t id) const; // get player info by unique player ID 365 C4PlayerInfo *GetPlayerInfoByID(int32_t id, int32_t *pidClient) const; // get player info by unique player ID, and assign associated client 366 C4ClientPlayerInfos *GetClientInfoByPlayerID(int32_t id) const; // get client info that contains a specific player 367 C4PlayerInfo *GetPlayerInfoBySavegameID(int32_t id) const;// get player info by savegame association ID 368 C4PlayerInfo *GetNextPlayerInfoByID(int32_t id) const; // get player info with smallest ID > given id 369 C4PlayerInfo *GetActivePlayerInfoByName(const char *szName); // find info by name (case insensitive) 370 int32_t GetPlayerCount() const; // get number of players on all clients 371 int32_t GetJoinIssuedPlayerCount() const; // get number of players with PIF_JoinIssued-flag set 372 int32_t GetJoinPendingPlayerCount() const; // get number of players with PIF_JoinIssued-flag but not joined or removed flag set 373 int32_t GetActivePlayerCount(bool fCountInvisible) const; // get number of players that have not been removed 374 StdStrBuf GetActivePlayerNames(bool fCountInvisible, int32_t iAtClientID=-1) const; // get a comma-separated list of players that have not been removed yet 375 int32_t GetActiveScriptPlayerCount(bool fCountSavegameResumes, bool fCountInvisible) const; // get number of script players that have not been removed GetPrimaryInfoByClientID(int32_t iClientID)376 C4PlayerInfo *GetPrimaryInfoByClientID(int32_t iClientID) const 377 { 378 C4ClientPlayerInfos *pInfoPkt = GetInfoByClientID(iClientID); 379 if (!pInfoPkt) return nullptr; 380 return pInfoPkt->GetPlayerInfo(0); 381 } 382 C4PlayerInfo *FindSavegameResumePlayerInfo(const C4PlayerInfo *pMatchInfo, MatchingLevel mlMatchStart, MatchingLevel mlMatchEnd) const; // automatic savegame player association: Associate by name (or prefcolor, if none matches) 383 bool HasSameTeamPlayers(int32_t iClient1, int32_t iClient2) const; // check all active players; return true if two of them on different clients are in the same team 384 C4PlayerInfo *FindUnassociatedRestoreInfo(const C4PlayerInfoList &rRestoreInfoList); // find a player in the given list that has not been associated by a player in this list 385 RemoveInfo(C4ClientPlayerInfos ** ppRemoveInfo)386 void RemoveInfo(C4ClientPlayerInfos **ppRemoveInfo) // remove client info given by direct ptr into list 387 { *ppRemoveInfo = ppClients[--iClientCount]; /* maybe redundant self-assignment; no vector shrink */ } 388 389 public: 390 bool Load(C4Group &hGroup, const char *szFromFile, class C4LangStringTable *pLang=nullptr); // clear self and load from group file 391 bool Save(C4Group &hGroup, const char *szToFile); // save to group file 392 393 // external ID counter manipulation used by C4Game SetIDCounter(int32_t idNewCounter)394 void SetIDCounter(int32_t idNewCounter) { iLastPlayerID = idNewCounter; } GetIDCounter()395 int32_t GetIDCounter() { return iLastPlayerID; } 396 void FixIDCounter(); // make sure ID counter is same as largest info 397 398 // game interaction 399 bool InitLocal(); // put locally joining players into list (non-network) 400 bool LocalJoinUnjoinedPlayersInQueue(); // join all unjoined players to local input queue 401 int32_t GetStartupCount(); // get number of players already joined and to be joined 402 void CreateRestoreInfosForJoinedScriptPlayers(C4PlayerInfoList &rSavegamePlayers); // create matching script player joins for all script playeers in restore info 403 bool RecreatePlayers(C4ValueNumbers *); // directly join all players whose join-flag is set 404 bool RecreatePlayerFiles(); // update player source files 405 bool RestoreSavegameInfos(C4PlayerInfoList &rSavegamePlayers); // recreate this list from rSavegamePlayers for host/single games; just merge associated infos 406 bool SetAsRestoreInfos(C4PlayerInfoList &rFromPlayers, bool fSaveUserPlrs, bool fSaveScriptPlrs, bool fSetUserPlrRefToLocalGroup, bool fSetScriptPlrRefToLocalGroup); // copy all joined players from player list 407 void RemoveUnassociatedPlayers(C4PlayerInfoList &rSavegamePlayers); // remove all savegame players that are not associated to this list from the game 408 int32_t GetFreePlayerSlotCount(); // get number of players that may still join 409 void ResetLeagueProjectedGain(bool fSetUpdated); // reset known projected gains for all players (to be updated by league again) 410 411 // network: Load all resources connected with the players that are not being loaded yet 412 void LoadResources(); 413 414 // compiler 415 void CompileFunc(StdCompiler *pComp); 416 }; 417 418 #endif // INC_C4PlayerInfo 419