void C4Network2Players::HandlePlayerInfo(const class C4ClientPlayerInfos &rInfoPacket) { // network only assert(::Network.isEnabled()); // copy client player infos out of packet to be used in local list C4ClientPlayerInfos *pClientInfo = new C4ClientPlayerInfos(rInfoPacket); // add client info to local player info list - eventually deleting pClientInfo and // returning a pointer to the new info structure when multiple player infos are merged // may also replace existing info, if this is an update-call pClientInfo = rInfoList.AddInfo(pClientInfo); // make sure team list reflects teams set in player infos Game.Teams.RecheckPlayers(); Game.Teams.RecheckTeams(); // recheck random teams - if a player left, teams may need to be rebalanced // make sure resources are loaded for those players rInfoList.LoadResources(); // get associated client - note that pClientInfo might be NULL for empty packets that got discarded if (pClientInfo) { const C4Client *pClient = Game.Clients.getClientByID(pClientInfo->GetClientID()); // host, game running and client active already? if (::Network.isHost() && ::Network.isRunning() && pClient && pClient->isActivated()) { // then join the players immediately JoinUnjoinedPlayersInControlQueue(pClientInfo); } } // adding the player may have invalidated other players (through team settings). Send them. SendUpdatedPlayers(); // lobby: update players C4GameLobby::MainDlg *pLobby = ::Network.GetLobby(); if (pLobby) pLobby->OnPlayersChange(); // invalidate reference ::Network.InvalidateReference(); }
C4ClientPlayerInfos *C4Network2Players::GetLocalPlayerInfoPacket() const { // get local client ID int iLocalClientID = Game.Clients.getLocalID(); // check all packets for same client ID as local int i=0; C4ClientPlayerInfos *pkInfo; while ((pkInfo = rInfoList.GetIndexedInfo(i++))) if (pkInfo->GetClientID() == iLocalClientID) // found return pkInfo; // not found return NULL; }
void C4Network2Players::UpdateSavegameAssignments(C4ClientPlayerInfos *pNewInfo) { // safety if (!pNewInfo) return; // check all joins of new info; backwards so they can be deleted C4PlayerInfo *pInfo, *pInfo2, *pSaveInfo; int i=pNewInfo->GetPlayerCount(), j, id; while (i--) if ((pInfo = pNewInfo->GetPlayerInfo(i))) if ((id=pInfo->GetAssociatedSavegamePlayerID())) { // check for non-existant savegame players if (!(pSaveInfo=Game.RestorePlayerInfos.GetPlayerInfoByID(id))) { pInfo->SetAssociatedSavegamePlayer(id=0); pNewInfo->SetUpdated(); } // check for duplicates (can't really occur...) if (id) { j=i; while ((pInfo2 = pNewInfo->GetPlayerInfo(++j))) if (pInfo2->GetAssociatedSavegamePlayerID() == id) { // fix it by resetting the savegame info pInfo->SetAssociatedSavegamePlayer(id=0); pNewInfo->SetUpdated(); break; } } // check against all infos of other clients C4ClientPlayerInfos *pkClientInfo; int k=0; while ((pkClientInfo = rInfoList.GetIndexedInfo(k++)) && id) { // if it's not an add packet, don't check own client twice if (pkClientInfo->GetClientID() == pNewInfo->GetClientID() && !(pNewInfo->IsAddPacket())) continue; // check against all players j=0; while ((pInfo2 = pkClientInfo->GetPlayerInfo(j++))) if (pInfo2->GetAssociatedSavegamePlayerID() == id) { // fix it by resetting the savegame info pInfo->SetAssociatedSavegamePlayer(id=0); pNewInfo->SetUpdated(); break; } } // if the player joined just for the savegame assignment, and that failed, delete it if (!id && pInfo->IsJoinForSavegameOnly()) pNewInfo->RemoveIndexedInfo(i); // prev info } }
void C4Network2Players::OnStatusGoReached() { // host only if (!::Network.isHost()) return; // check all player lists int i=0; C4ClientPlayerInfos *pkInfo; while ((pkInfo = rInfoList.GetIndexedInfo(i++))) // any unsent player joins? if (pkInfo->HasUnjoinedPlayers()) { // get client core const C4Client *pClient = Game.Clients.getClientByID(pkInfo->GetClientID()); // don't send if client is unknown or not activated yet if (!pClient || !pClient->isActivated()) continue; // send them w/o info packet // info packets are synced during pause mode JoinUnjoinedPlayersInControlQueue(pkInfo); } }