1129 lines
35 KiB
Ucode
1129 lines
35 KiB
Ucode
//=============================================================================
|
|
// KFGFxServerBrowser_ServerList
|
|
//=============================================================================
|
|
// Class Description
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
|
// - Zane 8/19/2014
|
|
//=============================================================================
|
|
|
|
class KFGFxServerBrowser_ServerList extends KFGFxObject_Container
|
|
native(UI)
|
|
config(UI);
|
|
|
|
/** Reference to the search datastore. */
|
|
var transient KFDataStore_OnlineGameSearch SearchDataStore;
|
|
|
|
/** stores the password entered by the user when attempting to connect to a server with a password */
|
|
var private transient string ServerPassword;
|
|
|
|
/** True if we want to join as a spectator */
|
|
var private transient bool bJoinAsSpectator;
|
|
|
|
var protected transient const name SearchDSName;
|
|
|
|
/** Cached online subsystem pointer */
|
|
var transient OnlineSubsystem OnlineSub;
|
|
|
|
/** Cached game interface pointer */
|
|
var transient OnlineGameInterface GameInterface;
|
|
|
|
//A cache for the server list gfx object so we do not have to create them everytime we refresh or update the list
|
|
var array<GFxObject> GFxServerObjects;
|
|
|
|
/** Is an informative dialog about the server browser currently displayed. */
|
|
var private transient bool bQueryDialogShowing;
|
|
|
|
var private transient bool bIssuedInitialQuery;
|
|
|
|
var private GFxObject DataProvider;
|
|
|
|
var public int FakePlayerIndex;
|
|
|
|
var public int SelectedServerIndex;
|
|
|
|
var localized string LeaveServerBrowserString;
|
|
|
|
var localized string DetailsString;
|
|
|
|
var localized string SpectateString;
|
|
|
|
var KFGFxMenu_ServerBrowser ServerMenu;
|
|
|
|
var transient int FilteredCount;
|
|
|
|
/** Maximum number of server entries in the browser */
|
|
var globalconfig int MaxSearchResults;
|
|
|
|
var int lastServerCount;
|
|
|
|
/**
|
|
* Different actions to take when a query completes.
|
|
*/
|
|
var private transient enum EQueryCompletionAction
|
|
{
|
|
/** no query action set */
|
|
QUERYACTION_None,
|
|
|
|
/** do nothing when the query completes; default behavior */
|
|
QUERYACTION_Default,
|
|
|
|
/**
|
|
* This is set when the user wants to close the scene but we still have active queries. When the queries are completed
|
|
* (either through being canceled or receiving all results), close the scene.
|
|
*/
|
|
QUERYACTION_CloseScene,
|
|
|
|
/**
|
|
* This is set when the user has chosen a server from the list. When the queries are completed or cancelled, join the currently selected server.
|
|
*/
|
|
QUERYACTION_JoinServer,
|
|
|
|
/**
|
|
* This is set when the user switches from LAN to Internet or vice versa. When the queries are completed of cancelled, clear all results and reissue the
|
|
* current query.
|
|
*/
|
|
QUERYACTION_RefreshAll,
|
|
|
|
} QueryCompletionAction;
|
|
|
|
var private transient enum ESearch_Tab
|
|
{
|
|
TAB_ALL,
|
|
TAB_FAVORITES,
|
|
TAB_FRIENDS,
|
|
TAB_HISTORY,
|
|
TAB_LAN,
|
|
TAB_MAX,
|
|
} ECurrentSearchTab;
|
|
|
|
struct native ExtraServerInfo
|
|
{
|
|
var bool ServerHeardBackFrom;
|
|
var bool GameRunning;
|
|
var bool RequestDispatched;
|
|
|
|
var int StartTimer; // if game has not started, how many seconds until it does
|
|
|
|
var float Ping; // direct ping to the server from x-tra fetch
|
|
var int Survivors; // current player count
|
|
var int SurvivorsAvgLevel;
|
|
var int ZedPlayers; // current zed-players for vs servers
|
|
};
|
|
|
|
//equivalent to OnViewLoaded from UDK/Unreal Tournement 3
|
|
function Initialize( KFGFxObject_Menu NewParentMenu )
|
|
{
|
|
local DataStoreClient DSClient;
|
|
|
|
super.Initialize( NewParentMenu );
|
|
ServerMenu =KFGFxMenu_ServerBrowser(NewParentMenu);
|
|
LocalizeText();
|
|
|
|
DSClient = class'UIInteraction'.static.GetDataStoreClient();
|
|
if ( DSClient != None )
|
|
{
|
|
SearchDataStore = KFDataStore_OnlineGameSearch(DSClient.FindDataStore(SearchDSName));
|
|
}
|
|
|
|
OnlineSub = class'GameEngine'.static.GetOnlineSubsystem();
|
|
GameInterface = OnlineSub.GameInterface;
|
|
|
|
//OnViewActivated();
|
|
}
|
|
|
|
function OnViewActivated()
|
|
{
|
|
//ScriptTrace();
|
|
//local UIDataStore_Registry Registry;
|
|
|
|
//Registry = UIDataStore_Registry(class'UIRoot'.static.StaticResolveDataStore('Registry'));
|
|
|
|
// Default to LAN.
|
|
//Registry.SetData("LanClient", "1");
|
|
|
|
// Decide whether we're playing LAN or Online and set MatchType appropriately.
|
|
ValidateServerType();
|
|
|
|
// Push an initial query when the page is first activated.
|
|
if ( !bIssuedInitialQuery )
|
|
{
|
|
bIssuedInitialQuery = TRUE;
|
|
RefreshServerList(FakePlayerIndex);
|
|
}
|
|
|
|
// Update the list's data provider.
|
|
UpdateListDataProvider();
|
|
}
|
|
|
|
function SortServerResultsRequest(int ButtonIndex, int SortOrder)
|
|
{
|
|
local KFOnlineGameSearch LatestGameSearch;
|
|
|
|
LatestGameSearch = KFOnlineGameSearch(SearchDataStore.GetActiveGameSearch());
|
|
if(LatestGameSearch == none)
|
|
{
|
|
return;
|
|
}
|
|
LatestGameSearch.SortResults(ESortType(ButtonIndex), ESortOrder(SortOrder));
|
|
UpdateListDataProvider();
|
|
}
|
|
|
|
/**
|
|
* Enables / disables the "match type" control based on whether we are signed in online.
|
|
*/
|
|
function ValidateServerType()
|
|
{
|
|
local int PlayerIndex, PlayerControllerID;
|
|
local LocalPlayer LP;
|
|
|
|
// Don't worry about remote players
|
|
LP = LocalPlayer(GetPC().Player);
|
|
|
|
// don't have a link connection, or not allowed to play online, don't allow them to select one.
|
|
PlayerIndex = class'UIInteraction'.static.GetPlayerIndex(LP.ControllerID);
|
|
PlayerControllerID = class'UIInteraction'.static.GetPlayerControllerId( PlayerIndex );
|
|
if (!class'UIInteraction'.static.IsLoggedIn(PlayerControllerID, true))
|
|
{
|
|
`log("MUST BE LOGGED IN TO GET SEARCH RESULTS");
|
|
//FORCE A LAN SEARCH HERE. Attempting an online search here will crash the game if you are not signed into Steam ** IF WE SUPPORT IT **
|
|
}
|
|
}
|
|
|
|
function ChangeSearchType(ESteamMatchmakingType SearchType, optional bool bPreventNewSearch)
|
|
{
|
|
GameInterface.SetMatchmakingTypeMode(SearchType);
|
|
if(!bPreventNewSearch)
|
|
{
|
|
RefreshServerList(FakePlayerIndex);
|
|
}
|
|
}
|
|
|
|
function LocalizeText()
|
|
{
|
|
local GFxObject LocalizedObject;
|
|
LocalizedObject = CreateObject( "Object" );
|
|
|
|
LocalizedObject.SetString("players", ServerMenu.PlayersString);
|
|
LocalizedObject.SetString("name", ServerMenu.NameString);
|
|
LocalizedObject.SetString("mode", ServerMenu.GameModeString);
|
|
LocalizedObject.SetString("difficulty", ServerMenu.DifficultyString);
|
|
LocalizedObject.SetString("map", ServerMenu.MapString);
|
|
LocalizedObject.SetString("filters", ServerMenu.FiltersString);
|
|
LocalizedObject.SetString("search", ServerMenu.SearchString);
|
|
LocalizedObject.SetString("refresh", ServerMenu.RefreshString);
|
|
LocalizedObject.SetString("gamesFound", ServerMenu.GamesFoundString);
|
|
|
|
LocalizedObject.SetString("back", LeaveServerBrowserString );
|
|
LocalizedObject.SetString("details", DetailsString);
|
|
LocalizedObject.SetString("spectate", SpectateString);
|
|
LocalizedObject.SetString("join", ServerMenu.JoinString);
|
|
|
|
SetObject("localizedText", LocalizedObject);
|
|
}
|
|
|
|
function OnRefeshClick()
|
|
{
|
|
RefreshServerList(FakePlayerIndex);
|
|
}
|
|
|
|
function ClearGFXServerList()
|
|
{
|
|
local GFxObject TempArray;
|
|
|
|
TempArray = CreateArray();
|
|
|
|
SetObject("dataProvider", TempArray);
|
|
}
|
|
|
|
/** Refreshes the server list. */
|
|
function RefreshServerList(int InPlayerIndex)
|
|
{
|
|
local KFOnlineGameSearch GameSearch;
|
|
|
|
if(SearchDataStore == none) {
|
|
`log("Can't refresh server list without a Search DS!");
|
|
return;
|
|
}
|
|
|
|
ClearGFXServerList();
|
|
|
|
//This submits the server list query
|
|
CancelQuery(QUERYACTION_RefreshAll);
|
|
|
|
// Get current filter from the string list datastore
|
|
GameSearch = KFOnlineGameSearch(SearchDataStore.GetCurrentGameSearch());
|
|
|
|
// Set max results
|
|
if(ServerMenu.FiltersContainer.bLimitServerResults)
|
|
{
|
|
GameSearch.MaxSearchResults = Max(MaxSearchResults, 1);
|
|
}
|
|
else
|
|
{
|
|
GameSearch.MaxSearchResults = MaxInt;
|
|
}
|
|
|
|
}
|
|
|
|
function BuildServerFilters(KFGFxServerBrowser_Filters Filters, OnlineGameSearch Search)
|
|
{
|
|
local string GametagSearch;
|
|
local string MapName;
|
|
local int Mode, Difficulty, Length, WeeklySelectorIndex;
|
|
local bool DisableSeasonalSkins;
|
|
|
|
Search.ClearServerFilters();
|
|
|
|
Search.AddServerFilter("version_match", string(class'KFGameEngine'.static.GetKFGameVersion()));
|
|
Search.TestAddServerFilter( Filters.bNotFull, "notfull");
|
|
Search.TestAddServerFilter( Filters.bNotEmpty, "hasplayers");
|
|
Search.TestAddBoolGametagFilter(GametagSearch, Filters.bNoLocalAdmin, 'bServerExiled', 0);
|
|
|
|
DisableSeasonalSkins = Filters.bNoSeasonalSkins;
|
|
|
|
if (class'KFGameEngine'.static.GetSeasonalEventIDForZedSkins() == SEI_None
|
|
|| class'KFGameEngine'.static.GetSeasonalEventIDForZedSkins() == SEI_Spring)
|
|
{
|
|
DisableSeasonalSkins = false;
|
|
}
|
|
|
|
Search.TestAddBoolGametagFilter(GametagSearch, DisableSeasonalSkins, 'bNoSeasonalSkins', 1);
|
|
|
|
if( !class'WorldInfo'.static.IsConsoleBuild() )
|
|
{
|
|
Search.TestAddServerFilter( Filters.bDedicated, "dedicated");
|
|
if( !class'WorldInfo'.static.IsEOSBuild() )
|
|
{
|
|
Search.TestAddServerFilter( Filters.bVAC_Secure, "secure");
|
|
}
|
|
}
|
|
|
|
MapName = Filters.GetSelectedMap();
|
|
if (MapName != "")
|
|
{
|
|
Search.AddServerFilter( "map", MapName);
|
|
}
|
|
|
|
if (Filters.bInProgress && !Filters.bInLobby)
|
|
{
|
|
Search.TestAddBoolGametagFilter(GametagSearch, Filters.bInProgress, 'bInProgress', 1);
|
|
}
|
|
else if (Filters.bInLobby)
|
|
{
|
|
Search.TestAddBoolGametagFilter(GametagSearch, Filters.bInLobby, 'bInProgress', 0);
|
|
}
|
|
|
|
if( !class'WorldInfo'.static.IsConsoleBuild() )
|
|
{
|
|
Search.TestAddBoolGametagFilter(GametagSearch, Filters.bNoPassword, 'bRequiresPassword', 0);
|
|
}
|
|
|
|
Mode = Filters.SavedGameModeIndex;
|
|
if( Mode >= 0 && Mode < 255 )
|
|
{
|
|
Search.AddGametagFilter( GametagSearch, 'Mode', string(Mode) );
|
|
}
|
|
|
|
Difficulty = Filters.GetSelectedDifficulty();
|
|
if (Difficulty >= 0)
|
|
{
|
|
Search.AddGametagFilter(GametagSearch, 'Difficulty', string(Difficulty));
|
|
}
|
|
|
|
Length = Filters.GetSelectedGameLength();
|
|
if (Length >= 0)
|
|
{
|
|
Search.AddGametagFilter(GametagSearch, 'NumWaves', string(Length));
|
|
}
|
|
|
|
//`log("bCustom="$Filters.bCustom);
|
|
if(Filters.bCustom && !class'WorldInfo'.static.IsConsoleBuild() )
|
|
{
|
|
//`log("adding custom filter");
|
|
Search.TestAddBoolGametagFilter(GametagSearch, Filters.bCustom, 'bCustom', 0);
|
|
}
|
|
|
|
WeeklySelectorIndex = Filters.GetWeeklySelectorIndex();
|
|
if (Mode == 1 && WeeklySelectorIndex != 0) // // Only when mode is Weekly, 0 means "ANY", 1 is "DEFAULT", then the weeklies
|
|
{
|
|
WeeklySelectorIndex = WeeklySelectorIndex - 1; // move back to index range
|
|
|
|
Search.AddGametagFilter(GametagSearch, 'WeeklySelectorIndex', string(WeeklySelectorIndex));
|
|
}
|
|
|
|
if (Len(GametagSearch) > 0)
|
|
{
|
|
Search.AddServerFilter( "gametagsand", GametagSearch);
|
|
}
|
|
if (Search.MasterServerSearchKeys.length > 1)
|
|
{
|
|
Search.AddServerFilter( "and", string(Search.MasterServerSearchKeys.length), 0);
|
|
}
|
|
//@SABER_BEGIN - Saving the value for ping filter in server search parameters
|
|
if (class'WorldInfo'.static.IsEOSBuild())
|
|
{
|
|
Search.MaxPing = Filters.GetMaxPing();
|
|
}
|
|
//@SABER_END
|
|
}
|
|
|
|
/**
|
|
* Submits a query for the list of servers which match the current configuration.
|
|
*/
|
|
function SubmitServerListQuery( int PlayerIndex )
|
|
{
|
|
// ToDo delete
|
|
`log("SubmitServerListQuery called!");
|
|
//ScriptTrace();
|
|
BuildServerFilters(ServerMenu.FiltersContainer, SearchDataStore.GetCurrentGameSearch());
|
|
|
|
if( class'WorldInfo'.static.IsConsoleBuild() || class'WorldInfo'.static.IsEOSBuild())
|
|
{
|
|
class'GameEngine'.static.GetPlayfabInterface().AddFindOnlineGamesCompleteDelegate( OnFindOnlineGamesCompleteDelegate );
|
|
}
|
|
else
|
|
{
|
|
// Add a delegate for when the search completes. We will use this callback to do any post searching work.
|
|
GameInterface.AddFindOnlineGamesCompleteDelegate(OnFindOnlineGamesCompleteDelegate);
|
|
}
|
|
|
|
// Start a search
|
|
if ( !SearchDataStore.SubmitGameSearch(class'UIInteraction'.static.GetPlayerControllerId(PlayerIndex), false) )
|
|
{
|
|
if( class'WorldInfo'.static.IsConsoleBuild() || class'WorldInfo'.static.IsEOSBuild())
|
|
{
|
|
class'GameEngine'.static.GetPlayfabInterface().ClearFindOnlineGamesCompleteDelegate( OnFindOnlineGamesCompleteDelegate );
|
|
}
|
|
else
|
|
{
|
|
GameInterface.ClearFindOnlineGamesCompleteDelegate(OnFindOnlineGamesCompleteDelegate);
|
|
}
|
|
|
|
//Set Refreshing to false **UI of we want to show it**
|
|
SetRefreshingIndicator(false);
|
|
}
|
|
else
|
|
{
|
|
//We're starting a new search, create a new DataProvider array
|
|
FilteredCount = 0;
|
|
DataProvider = CreateArray();
|
|
SetRefreshingIndicator(true);
|
|
}
|
|
}
|
|
/**
|
|
* @return True if the entry was filtered, false if it wasn't
|
|
*/
|
|
native function bool FilterEntry(OnlineGameSearch Search, KFGFxServerBrowser_Filters filter, int entry);
|
|
|
|
/**
|
|
* Delegate fired each time a new server is received, or when the action completes (if there was an error)
|
|
*
|
|
* @param bWasSuccessful true if the async action completed without error, false if there was an error
|
|
*/
|
|
function OnFindOnlineGamesCompleteDelegate(bool bWasSuccessful)
|
|
{
|
|
local bool bSearchCompleted;
|
|
local OnlineGameSearch Search;
|
|
|
|
`log("OnFindOnlineGamesCompleteDelegate called!, bWasSuccessful is" @ bWasSuccessful);
|
|
Search = SearchDataStore.GetActiveGameSearch();
|
|
bSearchCompleted = Search == none || Search.Results.length == lastServerCount;
|
|
if ( !bSearchCompleted )
|
|
{
|
|
if ( Search.Results.length > 0 && (!ServerMenu.ApplyFilters || !FilterEntry(Search, ServerMenu.FiltersContainer, Search.Results.length-1)) )
|
|
{
|
|
`TimerHelper.SetTimer( 0.01, false, nameof(UpdateListDataProvider), self );
|
|
}
|
|
lastServerCount = Search.Results.length;
|
|
}
|
|
else
|
|
{
|
|
`log("OnFindOnlineGamesCompleteDelegate complete!");
|
|
|
|
if( class'WorldInfo'.static.IsConsoleBuild() || class'WorldInfo'.static.IsEOSBuild())
|
|
{
|
|
class'GameEngine'.static.GetPlayfabInterface().ClearFindOnlineGamesCompleteDelegate( OnFindOnlineGamesCompleteDelegate );
|
|
}
|
|
else
|
|
{
|
|
GameInterface.ClearFindOnlineGamesCompleteDelegate(OnFindOnlineGamesCompleteDelegate);
|
|
}
|
|
|
|
OnFindOnlineGamesComplete(bWasSuccessful);
|
|
lastServerCount = -1;
|
|
}
|
|
|
|
// update the enabled state of the button bar buttons
|
|
//UpdateButtonStates();
|
|
}
|
|
|
|
function OnClose()
|
|
{
|
|
`log("KFGFxServerBrowser_ServerList::OnClose called.");
|
|
//Make sure delegate isn't still set
|
|
CancelQuery(QUERYACTION_CloseScene);
|
|
ChangeSearchType(SMT_Internet, true);
|
|
KFGameEngine(Class'Engine'.static.GetEngine()).OnHandshakeComplete = None;
|
|
|
|
if( class'WorldInfo'.static.IsConsoleBuild() || class'WorldInfo'.static.IsEOSBuild())
|
|
{
|
|
class'GameEngine'.static.GetPlayfabInterface().ClearFindOnlineGamesCompleteDelegate( OnFindOnlineGamesCompleteDelegate );
|
|
class'GameEngine'.static.GetPlayfabInterface().ClearQueryServerInfoCompleteDelegate( OnQueryAdditionalServerInfoComplete );
|
|
if (class'WorldInfo'.static.IsEOSBuild()) {
|
|
class'GameEngine'.static.GetPlayfabInterface().ClearGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GameInterface.ClearFindOnlineGamesCompleteDelegate(OnFindOnlineGamesCompleteDelegate);
|
|
GameInterface.ClearJoinOnlineGameCompleteDelegate(OnJoinGameComplete);
|
|
GameInterface.ClearCancelFindOnlineGamesCompleteDelegate(OnCancelSearchComplete);
|
|
GameInterface.ClearGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
}
|
|
}
|
|
|
|
function OnGetPlayerListComplete(OnlineGameSettings Settings, bool Success)
|
|
{
|
|
local int i;
|
|
if (SearchDataStore.GetCurrentGameSearch().Results[SelectedServerIndex].GameSettings != Settings)
|
|
{
|
|
`log("KFGFxServerBrowser_ServerList.OnGetPlayerListComplete got player list for unselected server",, 'DevOnline');
|
|
return;
|
|
}
|
|
|
|
if (class'WorldInfo'.static.IsEOSBuild()) {
|
|
class'GameEngine'.static.GetPlayfabInterface().ClearGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
} else {
|
|
GameInterface.ClearGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
}
|
|
|
|
if (Success)
|
|
{
|
|
ServerMenu.ServerDetailsContainer.UpdatePlayerList(Settings);
|
|
`log("***Server Browser got player list:");
|
|
for (i = 0; i < Settings.PlayersInGame.Length; ++i)
|
|
{
|
|
`log(i+1 $ ":" @ Settings.PlayersInGame[i].PlayerName);
|
|
}
|
|
`log("***End of player list");
|
|
}
|
|
else
|
|
{
|
|
`log("***Server didn't respond with player list!");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delegate fired when the search for an online game has completed
|
|
*
|
|
* @param bWasSuccessful true if the async action completed without error, false if there was an error
|
|
*/
|
|
function OnFindOnlineGamesComplete(bool bWasSuccessful)
|
|
{
|
|
// ToDo delete
|
|
`log("OnFindOnlineGamesComplete called!");
|
|
SetRefreshingIndicator(false);
|
|
if ( QueryCompletionAction != QUERYACTION_None )
|
|
{
|
|
/*if ( bQueryDialogShowing )
|
|
{
|
|
MenuManager.PopView();
|
|
bQueryDialogShowing = false;
|
|
}
|
|
else
|
|
{*/
|
|
OnCancelSearchComplete(true);
|
|
//}
|
|
}
|
|
|
|
// refresh the list with the items from the currently selected gametype's cached query
|
|
|
|
}
|
|
|
|
/**
|
|
* Fires an asynchronous task to cancels all active queries.
|
|
*
|
|
* @param DesiredCancelAction specifies what should happen when the asynchronous task completes.
|
|
*/
|
|
function CancelQuery( optional EQueryCompletionAction DesiredCancelAction=QUERYACTION_Default )
|
|
{
|
|
// ToDo delete
|
|
`Log("CancelQuery called!");
|
|
if ( QueryCompletionAction == QUERYACTION_None )
|
|
{
|
|
QueryCompletionAction = DesiredCancelAction;
|
|
if ( SearchDataStore.GetActiveGameSearch() != none )
|
|
{
|
|
if( class'WorldInfo'.static.IsConsoleBuild() || class'WorldInfo'.static.IsEOSBuild())
|
|
{
|
|
class'GameEngine'.static.GetPlayfabInterface().CancelGameSearch();
|
|
OnCancelSearchComplete(true);
|
|
}
|
|
else
|
|
{
|
|
// we don't check for none so that we get warning in the log if GameInterface is none (this would be bad)
|
|
GameInterface.AddCancelFindOnlineGamesCompleteDelegate(OnCancelSearchComplete);
|
|
GameInterface.CancelFindOnlineGames();
|
|
}
|
|
}
|
|
else if ( SearchDataStore.GetCurrentGameSearch().Results.length > 0 || QueryCompletionAction == QUERYACTION_RefreshAll )
|
|
{
|
|
OnCancelSearchComplete(true);
|
|
}
|
|
// If no cancel delegate will get kicked off, reset the QueryCompletionAction value, or it gets stuck in 'cancelling' mode
|
|
else
|
|
{
|
|
QueryCompletionAction = QUERYACTION_None;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
`log("Could not cancel query because query cancel already in progress:" @ GetEnum(enum'EQueryCompletionAction', QueryCompletionAction));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Handler for the 'cancel query' asynchronous task completion. Performs the actions dictated by the current QueryCompletionAction, as
|
|
* set when CancelQuery was called.
|
|
*/
|
|
function OnCancelSearchComplete( bool bWasSuccessful )
|
|
{
|
|
local EQueryCompletionAction CurrentAction;
|
|
GameInterface.ClearCancelFindOnlineGamesCompleteDelegate(OnCancelSearchComplete);
|
|
|
|
CurrentAction = QueryCompletionAction;
|
|
QueryCompletionAction = QUERYACTION_None;
|
|
SetRefreshingIndicator(false);
|
|
|
|
switch ( CurrentAction )
|
|
{
|
|
case QUERYACTION_CloseScene:
|
|
ClearSearchResults();
|
|
break;
|
|
|
|
case QUERYACTION_JoinServer:
|
|
JoinServer(SelectedServerIndex);
|
|
break;
|
|
|
|
case QUERYACTION_RefreshAll:
|
|
// if we're leaving the server browser area - clear all stored server query searches
|
|
ClearSearchResults();
|
|
|
|
// Refresh the server browser after our cancel query has completely finished
|
|
GetPC().SetTimer(0.25f, false, nameof(DelayedRefresh), self);
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/** If we've just cancelled our search, always delay the next search so the queries
|
|
* are not confused */
|
|
function DelayedRefresh()
|
|
{
|
|
SubmitServerListQuery(FakePlayerIndex);
|
|
}
|
|
|
|
function JoinServer(optional int SearchResultIndex = -1, optional string WithPassword = "", optional bool JoinAsSpectator = false)
|
|
{
|
|
local KFOnlineGameSettings ServerSettings;
|
|
local OnlineGameSearchResult SearchResult;
|
|
|
|
//ScriptTrace();
|
|
if( SearchResultIndex >= 0 && SearchResultIndex < SearchDataStore.GetCurrentGameSearch().Results.Length )
|
|
{
|
|
SearchResult = SearchDataStore.GetCurrentGameSearch().Results[SearchResultIndex];
|
|
} else
|
|
{
|
|
return;
|
|
// If the index is invalid, then we will assume its the query by ip result //leaving this in here because this is valid. Currently, OnlineGameSearch does not have this variable.
|
|
//SearchResult = SearchDataStore.GetCurrentGameSearch().QueryByIpResult;
|
|
}
|
|
|
|
// Store this in case we need it later
|
|
SelectedServerIndex = SearchResultIndex;
|
|
|
|
// Get the settings
|
|
ServerSettings = KFOnlineGameSettings(SearchResult.GameSettings);
|
|
if(ServerSettings == none)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Just try joining, password or other checks will come back before the travel
|
|
ServerPassword = WithPassword;
|
|
bJoinAsSpectator = JoinAsSpectator;
|
|
ProcessJoin(SearchResult);
|
|
}
|
|
|
|
|
|
private function ProcessJoin(OnlineGameSearchResult SearchResult)
|
|
{
|
|
// ToDo delete
|
|
`Log("ProcessJoin called!");
|
|
if ( GameInterface != None )
|
|
{
|
|
if (SearchResult.GameSettings != None)
|
|
{
|
|
if( (class'WorldInfo'.static.IsConsoleBuild() || class'WorldInfo'.static.IsEOSBuild()) && !class'WorldInfo'.static.IsE3Build() )
|
|
{
|
|
// Make sure EOS game has GameSettings for crossplay needs.
|
|
if ((GameInterface.GetGameSettings('Game') == None) && class'WorldInfo'.static.IsEOSBuild())
|
|
{
|
|
GameInterface.JoinOnlineGame(0, 'Game', SearchResult);
|
|
}
|
|
class'GameEngine'.static.GetPlayfabInterface().AddSearchResultToHistory( SearchResult.GameSettings.JoinString );
|
|
class'GameEngine'.static.GetPlayfabInterface().AddQueryServerInfoCompleteDelegate( OnQueryAdditionalServerInfoComplete );
|
|
class'GameEngine'.static.GetPlayfabInterface().QueryServerInfo( SearchResult.GameSettings.LobbyId );
|
|
}
|
|
else
|
|
{
|
|
// Set the delegate for notification
|
|
GameInterface.AddJoinOnlineGameCompleteDelegate(OnJoinGameComplete);
|
|
|
|
if (OnlineGameInterfaceImpl(GameInterface).GetGameSearch() != none)
|
|
{
|
|
`log("Already have an online game session when trying to join an online game. Destroying it.",,'DevOnline');
|
|
//Despite dire warnings to the contrary, DestroyOnlineGame completes synchronously.
|
|
GameInterface.DestroyOnlineGame('Game');
|
|
}
|
|
|
|
// Start the async task
|
|
GameInterface.JoinOnlineGame(0, 'Game', SearchResult);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OnJoinGameComplete('Game', false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ServerPassword = "";
|
|
bJoinAsSpectator = false;
|
|
}
|
|
}
|
|
|
|
function OnJoinGameComplete(name SessionName, bool bSuccessful)
|
|
{
|
|
local string URL;
|
|
|
|
// Figure out if we have an online subsystem registered
|
|
if (GameInterface != None)
|
|
{
|
|
if (bSuccessful)
|
|
{
|
|
// Get the platform specific information
|
|
if (GameInterface.GetResolvedConnectString(SessionName, URL))
|
|
{
|
|
KFGameViewportClient(LocalPlayer(GetPC().Player).ViewPortClient).LastConnectionAttemptAddress = URL;
|
|
`Log("- Join Game Successful, Traveling: " $ URL);
|
|
JoinGameURL();
|
|
}
|
|
}
|
|
// Remove the delegate from the list
|
|
|
|
|
|
GameInterface.ClearJoinOnlineGameCompleteDelegate(OnJoinGameComplete);
|
|
}
|
|
|
|
if( !bSuccessful )
|
|
{
|
|
if(GetServerDetails(SelectedServerIndex).bRequiresPassword)
|
|
{
|
|
ServerMenu.ShowPasswordPopup();
|
|
}
|
|
}
|
|
|
|
ServerPassword = "";
|
|
}
|
|
|
|
|
|
function OnQueryAdditionalServerInfoComplete( bool bWasSuccessful, string LobbyId, string ServerIp, int ServerPort, string ServerTicket )
|
|
{
|
|
local string OpenCommand;
|
|
|
|
`log("OnQueryAdditionalServerInfoComplete with success"@bWasSuccessful@"and lobbyID"@LobbyId@"and server IP"@ServerIp@"and port"@ServerPort);
|
|
class'GameEngine'.static.GetPlayfabInterface().ClearQueryServerInfoCompleteDelegate( OnQueryAdditionalServerInfoComplete );
|
|
|
|
if( !bWasSuccessful || ServerIp == "" )
|
|
{
|
|
// TODO: Popup?
|
|
`warn("Failed to connect to server for some reason");
|
|
}
|
|
else
|
|
{
|
|
OpenCommand = "open"@ServerIp$":"$ServerPort;
|
|
OpenCommand $= "?AuthTicket="$ServerTicket;
|
|
OpenCommand $= "?PlayfabPlayerId="$class'GameEngine'.static.GetPlayfabInterface().CachedPlayfabId;
|
|
|
|
if( bJoinAsSpectator )
|
|
{
|
|
OpenCommand $= "?SpectatorOnly=1";
|
|
}
|
|
|
|
if (class'WorldInfo'.static.IsEOSBuild() && ( ServerPassword != "" ))
|
|
{
|
|
OpenCommand $= "?Password=" $ ServerPassword;
|
|
}
|
|
|
|
KFGameEngine(Class'Engine'.static.GetEngine()).OnHandshakeComplete = OnHandshakeComplete;
|
|
|
|
`log("Going to connect with URL:"@OpenCommand);
|
|
ConsoleCommand( OpenCommand );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function bool OnHandshakeComplete(bool bSuccess, string Error, out int SuppressPasswordRetry)
|
|
{
|
|
KFGameEngine(Class'Engine'.static.GetEngine()).OnHandshakeComplete = None;
|
|
if (bSuccess)
|
|
{
|
|
OnlineSub.GetLobbyInterface().LobbyJoinServer(KFGameViewportClient(LocalPlayer(GetPC().Player).ViewPortClient).LastConnectionAttemptAddress);
|
|
}
|
|
SuppressPasswordRetry = 1;
|
|
`log("*******OnHandshakeComplete"@bSuccess@Error);
|
|
ScriptTrace();
|
|
return false;
|
|
}
|
|
|
|
private native function ServerConnect(string URL);
|
|
|
|
function JoinGameURL()
|
|
{
|
|
local string URL;
|
|
|
|
// Call the game specific function to appending/changing the URL
|
|
URL = BuildJoinURL();
|
|
|
|
KFGameEngine(Class'Engine'.static.GetEngine()).OnHandshakeComplete = OnHandshakeComplete;
|
|
//`log("join url:" @ URL);
|
|
// Get the resolved URL and build the part to start it
|
|
ServerConnect(URL);
|
|
ServerPassword = "";
|
|
}
|
|
|
|
function string BuildJoinURL()
|
|
{
|
|
local string ConnectURL;
|
|
|
|
ConnectURL = KFGameViewportClient(LocalPlayer(GetPC().Player).ViewPortClient).LastConnectionAttemptAddress;
|
|
|
|
if ( ServerPassword != "" )
|
|
{
|
|
ConnectURL $= "?Password=" $ ServerPassword;
|
|
OnlineSub.GetLobbyInterface().SetServerPassword(ServerPassword);
|
|
}
|
|
else
|
|
{
|
|
OnlineSub.GetLobbyInterface().SetServerPassword("");
|
|
}
|
|
|
|
if(bJoinAsSpectator)
|
|
{
|
|
ConnectURL $= "?SpectatorOnly=1";
|
|
}
|
|
ConnectURL $= OnlineSub.GetLobbyInterface().GetLobbyURLString();
|
|
//ConnectURL $= BuildJoinFiltersRequestURL();
|
|
return ConnectURL;
|
|
}
|
|
|
|
|
|
function string BuildJoinFiltersRequestURL()
|
|
{
|
|
local string FiltersURL;
|
|
local int GameDifficulty, WeeklySelectorIndex, IntendedWeeklyIndex;
|
|
|
|
GameDifficulty = ServerMenu.FiltersContainer.GetSelectedDifficulty();
|
|
|
|
if( ServerMenu.FiltersContainer.SavedGameModeIndex >= 0 )
|
|
{
|
|
FiltersURL $= "?Game="$class'KFGameInfo'.static.GetGameModeClassFromNum(ServerMenu.FiltersContainer.SavedGameModeIndex);
|
|
}
|
|
|
|
if( GameDifficulty >= 0)
|
|
{
|
|
FiltersURL $= "?Difficulty="$GameDifficulty;
|
|
}
|
|
|
|
if( ServerMenu.FiltersContainer.SavedLengthIndex >= 0 )
|
|
{
|
|
FiltersURL $= "?GameLength="$ServerMenu.FiltersContainer.SavedLengthIndex;
|
|
}
|
|
|
|
WeeklySelectorIndex = ServerMenu.FiltersContainer.SavedWeeklySelectorIndex;
|
|
|
|
if (ServerMenu.FiltersContainer.SavedGameModeIndex == 1
|
|
&& WeeklySelectorIndex != 0) // 0 means "ANY", 1 is "DEFAULT", then the weeklies
|
|
{
|
|
WeeklySelectorIndex = WeeklySelectorIndex - 1; // move back to index range
|
|
|
|
// IF index matches default, set to 0 (default)
|
|
if (WeeklySelectorIndex >= 1)
|
|
{
|
|
IntendedWeeklyIndex = class'KFGameEngine'.static.GetIntendedWeeklyEventIndexMod();
|
|
if (IntendedWeeklyIndex == (WeeklySelectorIndex - 1))
|
|
{
|
|
WeeklySelectorIndex = 0;
|
|
}
|
|
}
|
|
|
|
if (WeeklySelectorIndex >= 0)
|
|
{
|
|
FiltersURL $= "?WeeklySelectorIndex=" $WeeklySelectorIndex;
|
|
}
|
|
}
|
|
|
|
return FiltersURL;
|
|
}
|
|
|
|
function OnRefreshServerDetails()
|
|
{
|
|
local KFOnlineGameSearch GameSearch;
|
|
|
|
GameSearch = KFOnlineGameSearch(SearchDataStore.GetCurrentGameSearch());
|
|
|
|
if(GameSearch != none)
|
|
{
|
|
`log("Refeshing Server: " @GameSearch.Results[SelectedServerIndex].GameSettings.OwningPlayerName);
|
|
//send the once the server is refreshed, ServerDetailsContainer::SetDetails(KFOnlineGameSettings ServerResult);
|
|
}
|
|
}
|
|
|
|
function ClearSearchResults()
|
|
{
|
|
if(SearchDataStore != none)
|
|
{
|
|
SearchDataStore.ClearAllSearchResults();
|
|
}
|
|
}
|
|
|
|
function KFOnlineGameSettings GetServerDetails(int ServerIndex)
|
|
{
|
|
local KFOnlineGameSearch GameSearch;
|
|
local KFOnlineGameSettings KFOGS;
|
|
|
|
GameSearch = KFOnlineGameSearch(SearchDataStore.GetCurrentGameSearch());
|
|
|
|
if(GameSearch != none)
|
|
{
|
|
KFOGS = KFOnlineGameSettings(GameSearch.Results[ServerIndex].GameSettings);
|
|
}
|
|
return KFOGS;
|
|
}
|
|
|
|
function SetRefreshingIndicator(bool bRefreshing)
|
|
{
|
|
SetBool("refreshing", bRefreshing);
|
|
}
|
|
|
|
function OnServerSelected(int ServerIndex)
|
|
{
|
|
local bool success;
|
|
local PlayfabInterface PlayfabInter;
|
|
|
|
SelectedServerIndex = ServerIndex;
|
|
`log("***Attempting to get player list for server" @ SelectedServerIndex);
|
|
|
|
PlayfabInter = class'GameEngine'.static.GetPlayfabInterface();
|
|
if( class'WorldInfo'.static.IsEOSBuild() && PlayfabInter != none )
|
|
{
|
|
PlayfabInter.AddGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
success = SearchDataStore.FindServerPlayerList(SelectedServerIndex);
|
|
if (!success)
|
|
{
|
|
`log("***Failed to get player list for server" @ SelectedServerIndex);
|
|
PlayfabInter.ClearGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
}
|
|
} else {
|
|
GameInterface.AddGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
success = SearchDataStore.FindServerPlayerList(SelectedServerIndex);
|
|
if (!success)
|
|
{
|
|
`log("***Failed to get player list for server" @ SelectedServerIndex);
|
|
GameInterface.ClearGetPlayerListCompleteDelegate(OnGetPlayerListComplete);
|
|
}
|
|
}
|
|
}
|
|
|
|
//native function bool FilterEntry(KFOnlineGameSettings Settings);
|
|
|
|
function UpdateListDataProvider()
|
|
{
|
|
local int i, NewServerCount;
|
|
|
|
local GFxObject TempObj;
|
|
local KFOnlineGameSearch LatestGameSearch;
|
|
local int Ping, PlayerCount;
|
|
local KFOnlineGameSettings TempOnlineGamesSettings;
|
|
local KFWeeklyOutbreakInformation WeeklyInfo;
|
|
|
|
LatestGameSearch = KFOnlineGameSearch(SearchDataStore.GetActiveGameSearch());
|
|
|
|
if (LatestGameSearch != none && DataProvider != none )
|
|
{
|
|
for (i = 0; i < LatestGameSearch.Results.Length; i++)
|
|
{
|
|
if ( LatestGameSearch.Results[i].GameSettings.GfxId == INDEX_NONE || LatestGameSearch.Results[i].GameSettings.GfxId >= GFxServerObjects.length )
|
|
{
|
|
if ( NewServerCount > 10 )
|
|
{
|
|
// delay
|
|
`TimerHelper.SetTimer( 0.01, false, nameof(UpdateListDataProvider), self );
|
|
break;
|
|
}
|
|
TempOnlineGamesSettings = KFOnlineGameSettings(LatestGameSearch.Results[i].GameSettings);
|
|
|
|
if (class'WorldInfo'.static.IsEOSBuild() && i >= LatestGameSearch.MaxSearchResults)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//@SABER_EGS_BEGIN - Add to the list only servers with measured ping
|
|
if (class'WorldInfo'.static.IsEOSBuild() && TempOnlineGamesSettings.PingInMs == -1) {
|
|
`TimerHelper.SetTimer( 0.1, false, nameof(UpdateListDataProvider), self );
|
|
break;
|
|
}
|
|
//@SABER_EGS_END
|
|
|
|
TempObj = CreateObject("Object");
|
|
|
|
TempObj.SetString("serverName", TempOnlineGamesSettings.OwningPlayerName);
|
|
|
|
PlayerCount = TempOnlineGamesSettings.NumPublicConnections - TempOnlineGamesSettings.NumOpenPublicConnections;
|
|
|
|
if (PlayerCount < 0)
|
|
{
|
|
PlayerCount = 0;
|
|
}
|
|
|
|
TempObj.SetFloat("playerCount", PlayerCount);
|
|
TempObj.SetFloat("maxPlayerCount", TempOnlineGamesSettings.NumPublicConnections);
|
|
TempObj.SetFloat("waveCount", TempOnlineGamesSettings.CurrentWave);
|
|
TempObj.SetFloat("maxWaveCount", IsEndlessModeIndex(TempOnlineGamesSettings.Mode) ? INDEX_NONE : TempOnlineGamesSettings.NumWaves);
|
|
TempObj.SetFloat("zedCount", TempOnlineGamesSettings.ZedCount);
|
|
TempObj.SetFloat("maxZedCount", TempOnlineGamesSettings.MaxZedCount);
|
|
TempObj.SetBool("vacEnable", TempOnlineGamesSettings.bAntiCheatProtected);
|
|
TempObj.SetBool("mutators", TempOnlineGamesSettings.bMutators);
|
|
TempObj.SetBool("bRanked", TempOnlineGamesSettings.bUsesStats);
|
|
TempObj.SetBool("bCustom", TempOnlineGamesSettings.bCustom);
|
|
|
|
Ping = TempOnlineGamesSettings.PingInMs;
|
|
TempObj.SetString("ping", (Ping < 0) ? ("-") : (String(Ping)) );
|
|
TempObj.SetString("difficulty", Class'KFCommon_LocalizedStrings'.static.GetDifficultyString(TempOnlineGamesSettings.difficulty));
|
|
|
|
TempObj.SetString("mode", class'KFCommon_LocalizedStrings'.static.GetGameModeString(TempOnlineGamesSettings.Mode));
|
|
|
|
// If weekly we show the icon of the weekly type
|
|
if (IsWeeklyModeIndex(TempOnlineGamesSettings.Mode))
|
|
{
|
|
if (TempOnlineGamesSettings.WeeklySelectorIndex > 0)
|
|
{
|
|
WeeklyInfo = class'KFMission_LocalizedStrings'.static.GetWeeklyOutbreakInfoByIndex(TempOnlineGamesSettings.WeeklySelectorIndex - 1);
|
|
}
|
|
else
|
|
{
|
|
WeeklyInfo = class'KFMission_LocalizedStrings'.static.GetCurrentWeeklyOutbreakInfo();
|
|
}
|
|
|
|
TempObj.SetString("weeklyType", "img://"$WeeklyInfo.IconPath);
|
|
}
|
|
|
|
TempObj.SetString("map", TempOnlineGamesSettings.MapName);
|
|
TempObj.SetBool("locked", TempOnlineGamesSettings.bRequiresPassword);
|
|
TempObj.SetBool("serverExiled", TempOnlineGamesSettings.bServerExiled);
|
|
//Get Game State from var const databinding EOnlineGameState GameState;
|
|
TempObj.SetString("gameStatus", String(TempOnlineGamesSettings.GameState));
|
|
|
|
GFxServerObjects.AddItem(TempObj);
|
|
TempOnlineGamesSettings.GfxId = GFxServerObjects.Length - 1;
|
|
|
|
NewServerCount++;
|
|
}
|
|
|
|
|
|
if ( LatestGameSearch.Results[i].GameSettings.ElementIdx != i )
|
|
{
|
|
DataProvider.SetElementObject(i, GFxServerObjects[LatestGameSearch.Results[i].GameSettings.GfxId]);
|
|
LatestGameSearch.Results[i].GameSettings.ElementIdx = i;
|
|
}
|
|
}
|
|
SetObject("dataProvider", DataProvider);
|
|
}
|
|
}
|
|
|
|
function bool IsWeeklyModeIndex(int ModeIndex)
|
|
{
|
|
return ModeIndex == 1;
|
|
}
|
|
|
|
function bool IsEndlessModeIndex(int ModeIndex)
|
|
{
|
|
return ModeIndex == 3;
|
|
}
|
|
|
|
function bool IsSelectedServerFavorited(int ServerSearchIndex)
|
|
{
|
|
local PlayfabInterface PlayfabInter;
|
|
local OnlineGameSearch LatestGameSearch;
|
|
|
|
PlayfabInter = class'GameEngine'.static.GetPlayfabInterface();
|
|
if( class'WorldInfo'.static.IsEOSBuild() && PlayfabInter != none )
|
|
{
|
|
LatestGameSearch = SearchDataStore.GetActiveGameSearch();
|
|
return PlayfabInter.IsSearchResultInFavoritesList(LatestGameSearch, ServerSearchIndex);
|
|
} else {
|
|
return GameInterface.IsSearchResultInFavoritesList(ServerSearchIndex);
|
|
}
|
|
}
|
|
|
|
function bool SetSelectedServerFavorited(bool bFavorited)
|
|
{
|
|
local PlayfabInterface PlayfabInter;
|
|
local OnlineGameSearch LatestGameSearch;
|
|
|
|
PlayfabInter = class'GameEngine'.static.GetPlayfabInterface();
|
|
if (bFavorited)
|
|
{
|
|
if( class'WorldInfo'.static.IsEOSBuild() && PlayfabInter != none )
|
|
{
|
|
LatestGameSearch = SearchDataStore.GetActiveGameSearch();
|
|
return PlayfabInter.AddSearchResultToFavorites(LatestGameSearch, SelectedServerIndex);
|
|
} else {
|
|
return GameInterface.AddSearchResultToFavorites(SelectedServerIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( class'WorldInfo'.static.IsEOSBuild() && PlayfabInter != none )
|
|
{
|
|
LatestGameSearch = SearchDataStore.GetActiveGameSearch();
|
|
return PlayfabInter.RemoveSearchResultFromFavorites(LatestGameSearch, SelectedServerIndex);
|
|
} else {
|
|
return GameInterface.RemoveSearchResultFromFavorites(SelectedServerIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
cpptext
|
|
{
|
|
inline UBOOL CheckFilters(const UKFOnlineGameSettings& settings, const UKFGFxServerBrowser_Filters& filter);
|
|
}
|
|
|
|
DefaultProperties
|
|
{
|
|
lastServerCount=-1
|
|
FakePlayerIndex=0
|
|
ServerPassword=""
|
|
SearchDSName=KFGameSearch
|
|
bIssuedInitialQuery=FALSE
|
|
bQueryDialogShowing=FALSE
|
|
SelectedServerIndex=-1
|
|
} |