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);
		}
}