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 C4PlayerInfoListAttributeConflictResolver::MarkConflicts(C4ClientPlayerInfos &rCheckPacket, bool fTestOriginal) { C4PlayerInfo *pCheckAgainstInfo; // check current and original attribute against all player infos for (int32_t j=0; (pCheckAgainstInfo = rCheckPacket.GetPlayerInfo(j)); ++j) { if (pCheckAgainstInfo->IsUsingAttribute(eAttr)) if (!pResolveInfo->GetID() || pResolveInfo->GetID() != pCheckAgainstInfo->GetID()) if (pResolveInfo != pCheckAgainstInfo) { // current conflict is marked only if the checked packet has same of lower priority than the one compared to // if the priority is higher, the attribute shall be changed in the other, low priority info instead! bool fHasHigherPrio = (GetAttributePriorityDifference(pResolveInfo, pResolvePacket, pCheckAgainstInfo, &rCheckPacket) > 0); if (!fHasHigherPrio) if (IsAttributeConflict(pCheckAgainstInfo, pResolveInfo, C4PlayerInfo::PLRAL_Current)) fCurrentConflict = true; if (fTestOriginal) { if (IsAttributeConflict(pCheckAgainstInfo, pResolveInfo, C4PlayerInfo::PLRAL_Original)) { if (fHasHigherPrio && !fOriginalConflict && !pLowPrioOriginalConflictPacket) { // original attribute is taken by a low prio packet - do not mark an original conflict, but remember the packet // that's blocking it pLowPrioOriginalConflictPacket = &rCheckPacket; } else { // original attribute is taken by either one higher/equal priority by packet, or by two low prio packets // in this case, don't revert to original pLowPrioOriginalConflictPacket = nullptr; fOriginalConflict = true; } } if (IsAttributeConflict(pCheckAgainstInfo, pResolveInfo, C4PlayerInfo::PLRAL_Alternate)) { if (fHasHigherPrio && !fAlternateConflict && !pLowPrioAlternateConflictPacket) pLowPrioAlternateConflictPacket = &rCheckPacket; else fAlternateConflict = true; } } } } }
DWORD C4Network2Players::GetClientChatColor(int idForClient, bool fLobby) const { // return color of first joined player; force to white for unknown // deactivated always white const C4Client *pClient = Game.Clients.getClientByID(idForClient); if (pClient && pClient->isActivated()) { // get players for activated C4ClientPlayerInfos *pInfoPacket = rInfoList.GetInfoByClientID(idForClient); C4PlayerInfo *pPlrInfo; if (pInfoPacket && (pPlrInfo = pInfoPacket->GetPlayerInfo(0, C4PT_User))) { if (fLobby) return pPlrInfo->GetLobbyColor(); else return pPlrInfo->GetColor(); } } // default color return 0xffffff; }
void C4PlayerInfoListAttributeConflictResolver::ResolveInPacket() { // check all player infos fAnyChange = false; int32_t iCheck = 0; while ((pResolveInfo = pResolvePacket->GetPlayerInfo(iCheck++))) { // not already joined? Joined player must not change their attributes! if (pResolveInfo->HasJoined()) continue; DWORD dwPrevColor = pResolveInfo->GetColor(); StdStrBuf sPrevForcedName; sPrevForcedName.Copy(pResolveInfo->GetForcedName()); // check attributes: Name and color for (eAttr = C4PlayerInfo::PLRATT_Color; eAttr != C4PlayerInfo::PLRATT_Last; eAttr = (C4PlayerInfo::Attribute) (eAttr+1)) { if (eAttr == C4PlayerInfo::PLRATT_Color) { // no color change in savegame associations if (pResolveInfo->GetAssociatedSavegamePlayerID()) continue; // or forced team colors if (Game.Teams.IsTeamColors() && Game.Teams.GetTeamByID(pResolveInfo->GetTeam())) continue; } else if (eAttr == C4PlayerInfo::PLRATT_Name) { // no name change if a league name is used if (pResolveInfo->getLeagueAccount() && *pResolveInfo->getLeagueAccount()) continue; } // not if attributes are otherwise fixed (e.g., for script players) if (pResolveInfo->IsAttributesFixed()) continue; // resolve in this info ResolveInInfo(); } // mark change for return value if anything was changed if (pResolveInfo->GetColor() != dwPrevColor || (pResolveInfo->GetForcedName() != sPrevForcedName)) fAnyChange = true; // next player info check } // mark update if anything was changed if (fAnyChange) pResolvePacket->SetUpdated(); }