/* ======================== idLobby::CreateLobbyUserFromLocalUser This functions just defaults the session users to the signin manager local users ======================== */ lobbyUser_t idLobby::CreateLobbyUserFromLocalUser( const idLocalUser * localUser ) { lobbyUser_t lobbyUser; idStr::Copynz( lobbyUser.gamertag, localUser->GetGamerTag(), sizeof( lobbyUser.gamertag ) ); lobbyUser.peerIndex = -1; lobbyUser.lobbyUserID = lobbyUserID_t( localUser->GetLocalUserHandle(), lobbyType ); // Generate the lobby using a combination of local user id, and lobby type lobbyUser.disconnecting = false; // If we are in a game lobby (or dedicated game state lobby), and we have a party lobby running, assume we can grab the party token from our equivalent user in the party. if ( ( lobbyType == TYPE_GAME || lobbyType == TYPE_GAME_STATE ) && sessionCB->GetPartyLobby().IsLobbyActive() ) { if ( ( sessionCB->GetPartyLobby().parms.matchFlags & MATCH_REQUIRE_PARTY_LOBBY ) && !( sessionCB->GetPartyLobby().parms.matchFlags & MATCH_PARTY_INVITE_PLACEHOLDER ) ) { // copy some things from my party user const int myPartyUserIndex = sessionCB->GetPartyLobby().GetLobbyUserIndexByLocalUserHandle( lobbyUser.lobbyUserID.GetLocalUserHandle() ); if ( verify( myPartyUserIndex >= 0 ) ) { // Just in case lobbyUser_t * myPartyUser = sessionCB->GetPartyLobby().GetLobbyUser( myPartyUserIndex ); if ( myPartyUser != NULL ) { lobbyUser.partyToken = myPartyUser->partyToken; } } } } lobbyUser.UpdateClientMutableData( localUser ); NET_VERBOSE_PRINT( "NET: CreateLobbyUserFromLocalUser: party %08x name %s (%s)\n", lobbyUser.partyToken, lobbyUser.gamertag, GetLobbyName() ); return lobbyUser; }
/* ======================== idLobby::GetLobbyUserIdByOrdinal ======================== */ lobbyUserID_t idLobby::GetLobbyUserIdByOrdinal( int userIndex ) const { const lobbyUser_t * user = GetLobbyUser( userIndex ); if ( user == NULL ) { return lobbyUserID_t(); } if ( user->isBot ) { return user->lobbyUserID; } if ( !ValidateConnectedUser( user ) ) { return lobbyUserID_t(); } return user->lobbyUserID; }
/* ======================== idLobby::AllocLobbyUserSlotForBot ======================== */ lobbyUserID_t idLobby::AllocLobbyUserSlotForBot( const char * botName ) { lobbyUser_t botSessionUser; botSessionUser.peerIndex = peerIndexOnHost; botSessionUser.isBot = true; botSessionUser.disconnecting = false; idStr::Copynz( botSessionUser.gamertag, botName, sizeof( botSessionUser.gamertag ) ); localUserHandle_t localUserHandle( session->GetSignInManager().GetUniqueLocalUserHandle( botSessionUser.gamertag ) ); botSessionUser.lobbyUserID = lobbyUserID_t( localUserHandle, lobbyType ); lobbyUser_t * botUser = NULL; int sessionUserIndex = -1; // First, try to replace a disconnected user for ( int i = 0; i < GetNumLobbyUsers(); ++i ) { if ( IsLobbyUserDisconnected( i ) ) { lobbyUser_t * user = GetLobbyUser( i ); if ( verify( user != NULL ) ) { *user = botSessionUser; botUser = user; sessionUserIndex = i; break; } } } if ( botUser == NULL ) { if ( freeUsers.Num() == 0 ) { idLib::Warning( "NET: Out Of Session Users - Can't Add Bot %s!", botName ); return lobbyUserID_t(); } botUser = AllocUser( botSessionUser ); sessionUserIndex = userList.Num() - 1; } if ( !verify( botUser != NULL ) ) { idLib::Warning( "NET: Can't Find Session Slot For Bot!" ); return lobbyUserID_t(); } else { NET_VERBOSE_PRINT( "NET: Created Bot %s At Index %d \n", botUser->gamertag, sessionUserIndex ); } SendNewUsersToPeers( peerIndexOnHost, userList.Num() - 1, 1 ); // bot has been added to the lobby user list - update the peers so that they can see the bot too. return GetLobbyUser( sessionUserIndex )->lobbyUserID; }
/* ======================== idLobby::RemoveBotFromLobbyUserList ======================== */ void idLobby::RemoveBotFromLobbyUserList( lobbyUserID_t lobbyUserID ) { const int index = GetLobbyUserIndexByID( lobbyUserID ); lobbyUser_t * botUser = GetLobbyUser( index ); if ( botUser == NULL ) { assert( false ); idLib::Warning( "RemoveBotFromLobbyUserList: Invalid User Index!" ); return; } if ( !botUser->isBot ) { idLib::Warning( "RemoveBotFromLobbyUserList: User Index Is Not A Bot!" ); // don't accidentally disconnect a human player. return; } botUser->isBot = false; botUser->lobbyUserID = lobbyUserID_t(); FreeUser( botUser ); }
/* ================ idGameLocal::SyncPlayersWithLobbyUsers ================ */ void idGameLocal::SyncPlayersWithLobbyUsers( bool initial ) { idLobbyBase& lobby = session->GetActingGameStateLobbyBase(); if( !lobby.IsHost() ) { return; } idStaticList< lobbyUserID_t, MAX_CLIENTS > newLobbyUsers; // First, loop over lobby users, and see if we find a lobby user that we haven't registered for( int i = 0; i < lobby.GetNumLobbyUsers(); i++ ) { lobbyUserID_t lobbyUserID1 = lobby.GetLobbyUserIdByOrdinal( i ); if( !lobbyUserID1.IsValid() ) { continue; } if( !initial && !lobby.IsLobbyUserLoaded( lobbyUserID1 ) ) { continue; } // Now, see if we find this lobby user in our list bool found = false; for( int j = 0; j < MAX_PLAYERS; j++ ) { idPlayer* player = static_cast<idPlayer*>( entities[ j ] ); if( player == NULL ) { continue; } lobbyUserID_t lobbyUserID2 = lobbyUserIDs[j]; if( lobbyUserID1 == lobbyUserID2 ) { found = true; break; } } if( !found ) { // If we didn't find it, we need to create a player and assign it to this new lobby user newLobbyUsers.Append( lobbyUserID1 ); } } // Validate connected players for( int i = 0; i < MAX_PLAYERS; i++ ) { idPlayer* player = static_cast<idPlayer*>( entities[ i ] ); if( player == NULL ) { continue; } lobbyUserID_t lobbyUserID = lobbyUserIDs[i]; if( !lobby.IsLobbyUserValid( lobbyUserID ) ) { delete entities[ i ]; mpGame.DisconnectClient( i ); lobbyUserIDs[i] = lobbyUserID_t(); continue; } lobby.EnableSnapshotsForLobbyUser( lobbyUserID ); } while( newLobbyUsers.Num() > 0 ) { // Find a free player data slot to use for this new player int freePlayerDataIndex = -1; for( int i = 0; i < MAX_PLAYERS; ++i ) { idPlayer* player = static_cast<idPlayer*>( entities[ i ] ); if( player == NULL ) { freePlayerDataIndex = i; break; } } if( freePlayerDataIndex == -1 ) { break; // No player data slots (this shouldn't happen) } lobbyUserID_t lobbyUserID = newLobbyUsers[0]; newLobbyUsers.RemoveIndex( 0 ); mpGame.ServerClientConnect( freePlayerDataIndex ); Printf( "client %d connected.\n", freePlayerDataIndex ); lobbyUserIDs[ freePlayerDataIndex ] = lobbyUserID; // Clear this player's old usercmds. common->ResetPlayerInput( freePlayerDataIndex ); common->UpdateLevelLoadPacifier(); // spawn the player SpawnPlayer( freePlayerDataIndex ); common->UpdateLevelLoadPacifier(); ServerWriteInitialReliableMessages( freePlayerDataIndex, lobbyUserID ); } }