457 lines
17 KiB
Ucode
457 lines
17 KiB
Ucode
//=============================================================================
|
|
// PlayFabInterface
|
|
//=============================================================================
|
|
// Interface class for all playfab calls
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2016 Tripwire Interactive LLC
|
|
// - Author 4/5/2016
|
|
//=============================================================================
|
|
class PlayfabInterface extends Object
|
|
config(Engine)
|
|
native
|
|
inherits(FTickableObject);
|
|
|
|
`define FillAddDel(aname)\
|
|
if (`aname.Find(InDelegate) == INDEX_NONE)\
|
|
{\
|
|
`aname[`aname.Length] = InDelegate;\
|
|
}\
|
|
|
|
`define FillClearDel( aname )\
|
|
local int RemoveIndex;\
|
|
RemoveIndex = `aname.Find(InDelegate);\
|
|
if (RemoveIndex != INDEX_NONE)\
|
|
{\
|
|
`aname.Remove(RemoveIndex,1);\
|
|
}\
|
|
|
|
/** The current pending game search */
|
|
var OnlineGameSearch PendingGameSearch;
|
|
|
|
/** Game search for get player data */
|
|
var OnlineGameSearch TempGameSearch;
|
|
|
|
/** The playfab ID with successful login */
|
|
var const init string CachedPlayfabId;
|
|
/** The session ticket with successful login */
|
|
var const init string CachedSessionTicket;
|
|
|
|
/** The cached auth code for when talking to a backend */
|
|
var const init string CachedAuthCode;
|
|
/** Cached auth code for consuming entitlements. Used for XB1 only */
|
|
var const init string CachedAuthForEntitlements;
|
|
|
|
/** TRUE if login process has finished */
|
|
var const private bool bLoginProcessFinished;
|
|
|
|
/** The time of the last auth refresh to determine if re-auth is needed. Represents appseconds converted to an INT */
|
|
var const private INT LastAuthRefreshTime;
|
|
|
|
/** The time in seconds for when auth should be refreshed */
|
|
var const private INT SecondsForAuthRefreshTime;
|
|
|
|
/** The time to verify the certificate at */
|
|
var const private float VerifyCertificateTime;
|
|
|
|
/** The number of login attempts we've had */
|
|
var int LoginAttempts;
|
|
var const private int MaxRetryLoginAttempts;
|
|
|
|
|
|
/** The name of the catalog to use */
|
|
var const init private{private} config string CatalogName;
|
|
|
|
struct native RegionDefinition
|
|
{
|
|
var float Ping;
|
|
var bool RegionUp;
|
|
var init string Name;
|
|
var init string Address;
|
|
|
|
structdefaultproperties
|
|
{
|
|
Ping=-1.0
|
|
RegionUp=false
|
|
Name=""
|
|
Address=""
|
|
}
|
|
};
|
|
|
|
var const config array<RegionDefinition> KnownRegions;
|
|
|
|
/** The list of available region names */
|
|
// var const config array<string> RegionNames;
|
|
|
|
/** The list of favourite servers */
|
|
var array<string> FavouriteServers;
|
|
|
|
/** Server history */
|
|
var array<string> ServerHistory;
|
|
|
|
/** The current region index for the player */
|
|
var init string CurrRegionName;
|
|
|
|
/** Service label used to consume PSN entitlements */
|
|
var const int PlayfabNPServiceLabel;
|
|
|
|
/** The title data */
|
|
var native Map_Mirror TitleData{TMap<FString, FString>};
|
|
|
|
// SERVER ONLY
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** TRUE if this server was launched by playfab */
|
|
var const private{private} bool bLaunchedByPlayfab;
|
|
|
|
/** TRUE if this is a cloud server */
|
|
var const private{private} bool bCloudServer;
|
|
|
|
/** The lobby ID of the server */
|
|
var const init private{private} string CachedLobbyId;
|
|
|
|
/** Server ID used for registration with multiplay */
|
|
var const init private{private} string CachedServerId;
|
|
|
|
/** The elapsed time since the last heartbeat for the server */
|
|
var const private{private} float ElapsedTimeSinceLastHeartBeat;
|
|
|
|
/** The interval needed for sending heartbeats to playfab */
|
|
var const private{private} float HeartbeatInterval;
|
|
|
|
/** The cached game settings */
|
|
var private{private} OnlineGameSettings CachedGameSettings;
|
|
|
|
/** Countdown timer for attempting a re-register of the server */
|
|
var const private{private} float CountdownToReregister;
|
|
|
|
/** The interval for server re-register attempts. Only ever set if heartbeat or original registration fails */
|
|
var const private{private} float ReregisterInterval;
|
|
|
|
/** Endpoint APIs specified by multiplay via commandline */
|
|
var const init private{private} string AllocateAPIEndpoint;
|
|
var const init private{private} string DeallocateAPIEndpoint;
|
|
|
|
/** TRUE if server is actively allocated with backend */
|
|
var private{private} bool bServerAllocated;
|
|
/** TRUE if server is de-allocated. Can ONLY be true if bServerAllocated has ever been true */
|
|
var private{private} bool bServerDeallocated;
|
|
/** The timestamp at which the server was deallocated */
|
|
var const private{private} qword DeallocatedTimeStamp;
|
|
/** Elapsed time since last update for deallocated server */
|
|
var const private{private} float TimeSinceLastDeallocationUpdate;
|
|
/** The interval between updates for deallocated servers */
|
|
var const private{private} float DeallocateTimeUpdateInterval;
|
|
|
|
// SERVER END
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
/** Array of delegates to multicast */
|
|
var array<delegate<OnFindOnlineGamesComplete> > FindOnlineGamesCompleteDelegates;
|
|
var array<delegate<OnQueryServerInfoComplete> > OnQueryServerInfoCompleteDelegates;
|
|
var array<delegate<OnLoginComplete> > LoginCompleteDelegates;
|
|
var array<delegate<OnRegionQueryComplete> > RegionQueryCompleteDelegates;
|
|
var array<delegate<OnServerStarted> > ServerStartedDelegates;
|
|
var array<delegate<OnInventoryRead> > InventoryReadDelegates;
|
|
var array<delegate<OnTitleDataRead> > TitleDataReadDelegates;
|
|
var array<delegate<OnStoreDataRead> > StoreDataReadDelegates;
|
|
var array<delegate<OnCloudScriptExecutionComplete> > CloudScriptExecutionCompleteDelegates;
|
|
var array<delegate<OnGetPlayerListComplete> > GetPlayerListCompleteDelegates;
|
|
|
|
// Client API calls
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// Login to playfab service. Will create account if login fails
|
|
native function bool Login( string UserName );
|
|
delegate OnLoginComplete(bool bWasSuccessful, string SessionTicket, string PlayfabId);
|
|
function AddOnLoginCompleteDelegate( delegate<OnLoginComplete> InDelegate) { `FillAddDel(LoginCompleteDelegates); }
|
|
function ClearOnLoginCompleteDelegate( delegate<OnLoginComplete> InDelegate) { `FillClearDel(LoginCompleteDelegates); }
|
|
|
|
delegate OnGetPlayerListComplete(OnlineGameSettings PlayerListSettings, bool Success);
|
|
function AddGetPlayerListCompleteDelegate(delegate<OnGetPlayerListComplete> InDelegate) { `FillAddDel(GetPlayerListCompleteDelegates); }
|
|
function ClearGetPlayerListCompleteDelegate(delegate<OnGetPlayerListComplete> InDelegate) { `FillClearDel(GetPlayerListCompleteDelegates); }
|
|
|
|
/**
|
|
* For determining if a server that we got in our search results is in our favorite list
|
|
*
|
|
* @return true if the search result at the specified index is a favorite, false if not
|
|
*/
|
|
native function bool IsSearchResultInFavoritesList(OnlineGameSearch LatestGameSearch, int Index);
|
|
|
|
native function bool AddSearchResultToFavorites(OnlineGameSearch LatestGameSearch, int Index);
|
|
native function bool RemoveSearchResultFromFavorites(OnlineGameSearch LatestGameSearch, int Index);
|
|
|
|
native function bool AddSearchResultToHistory(string JoinString);
|
|
|
|
function native int GetRegionIndex(const out string RegionName);
|
|
function native SetDefaultRegion(const out string RegionName);
|
|
|
|
native function UpdateUserTitleDisplayName( string DisplayName );
|
|
native function UpdateUserName( string DisplayName );
|
|
native function UpdateUserData( string Key, string Data, string Permission );
|
|
|
|
native function GetUserName( string PlayfabId, int SelectedServerIndex, int PlayerIndex );
|
|
native function GetPlayerList( OnlineGameSearch SearchSettings, INT SelectedServerIndex );
|
|
native function CheckPlayerDisplayName( string PlayfabId );
|
|
native function GetUserData( array<string> Keys, bool CheckData );
|
|
native function QueryPlayfabClientTicket( string LobbyId );
|
|
|
|
// Logout of playfab services when we get disconnected
|
|
native function bool Logout();
|
|
|
|
// Read store data
|
|
native function ReadStoreData();
|
|
delegate OnStoreDataRead(bool bWasSuccessful);
|
|
function AddStoreDataReadCompleteDelegate( delegate<OnStoreDataRead> InDelegate) { `FillAddDel(StoreDataReadDelegates); }
|
|
function ClearStoreDataReadCompleteDelegate( delegate<OnStoreDataRead> InDelegate) { `FillClearDel(StoreDataReadDelegates); }
|
|
|
|
// Read inventory for local user
|
|
native function ReadInventory();
|
|
delegate OnInventoryRead(bool bWasSuccessful);
|
|
function AddInventoryReadCompleteDelegate( delegate<OnInventoryRead> InDelegate) { `FillAddDel(InventoryReadDelegates); }
|
|
function ClearInventoryReadCompleteDelegate( delegate<OnInventoryRead> InDelegate) { `FillClearDel(InventoryReadDelegates); }
|
|
|
|
// Read title data
|
|
native function ReadTitleData();
|
|
delegate OnTitleDataRead();
|
|
function AddTitleDataReadCompleteDelegate( delegate<OnTitleDataRead> InDelegate ) { `FillAddDel(TitleDataReadDelegates); }
|
|
function ClearTitleDataReadCompleteDelegate( delegate<OnTitleDataRead> InDelegate ) { `FillClearDel(TitleDataReadDelegates); }
|
|
// Retrieves title data value for a particular key
|
|
native function string GetTitleDataForKey( string InKey );
|
|
|
|
// Unlocks a container for the user
|
|
native function UnlockContainer(string ContainerId);
|
|
|
|
// WireService exchange interface
|
|
native function PerformRuleExchange( ExchangeRuleSets ForRuleset, bool AllButOne =false );
|
|
|
|
// Consumes entitlements
|
|
native function ConsumeEntitlements(optional bool bWasPurchase = false);
|
|
|
|
// Find online games. Results will show up in the search settings supplied if successful
|
|
native function bool FindOnlineGames( OnlineGameSearch SearchSettings );
|
|
delegate OnFindOnlineGamesComplete(bool bWasSuccessful);
|
|
function AddFindOnlineGamesCompleteDelegate(delegate<OnFindOnlineGamesComplete> InDelegate) { `FillAddDel(FindOnlineGamesCompleteDelegates); }
|
|
function ClearFindOnlineGamesCompleteDelegate(delegate<OnFindOnlineGamesComplete> InDelegate) { `FillClearDel(FindOnlineGamesCompleteDelegates); }
|
|
// Cancel the current game search
|
|
native function CancelGameSearch();
|
|
|
|
// Query info for a particular server
|
|
native function QueryServerInfo( const string LobbyId );
|
|
delegate OnQueryServerInfoComplete(bool bWasSuccessful, string LobbyId, string ServerIp, int ServerPort, string AuthTicket);
|
|
function AddQueryServerInfoCompleteDelegate( delegate<OnQueryServerInfoComplete> InDelegate) { `FillAddDel(OnQueryServerInfoCompleteDelegates); }
|
|
function ClearQueryServerInfoCompleteDelegate( delegate<OnQueryServerInfoComplete> InDelegate) { `FillClearDel(OnQueryServerInfoCompleteDelegates); }
|
|
|
|
// Query available regions
|
|
delegate OnRegionQueryComplete( bool bWasSuccessful, array<string> OutRegionNames );
|
|
native function QueryAvailableRegions();
|
|
function AddRegionQueryCompleteDelegate( delegate<OnRegionQueryComplete> InDelegate) { `FillAddDel(RegionQueryCompleteDelegates); }
|
|
function ClearRegionQueryCompleteDelegate( delegate<OnRegionQueryComplete> InDelegate) { `FillClearDel(RegionQueryCompleteDelegates); }
|
|
|
|
// Starts a new server instance
|
|
native function StartNewServerInstance( optional string ServerCommandline );
|
|
delegate OnServerStarted( bool bWasSuccessful, string ServerLobbyId, string ServerIp, int ServerPort, string ServerTicket );
|
|
function AddOnServerStartedDelegate( delegate<OnServerStarted> InDelegate) { `FillAddDel(ServerStartedDelegates); }
|
|
function ClearOnServerStartedDelegate( delegate<OnServerStarted> InDelegate) { `FillClearDel(ServerStartedDelegates); }
|
|
|
|
// Executes a cloud script function
|
|
native function ExecuteCloudScript( string FunctionName, JsonObject FunctionParms );
|
|
delegate OnCloudScriptExecutionComplete( bool bWasSuccessful, string FunctionName, JsonObject FunctionResult );
|
|
function AddOnCloudScriptExecutionCompleteDelegate( delegate<OnCloudScriptExecutionComplete> InDelegate ) { `FillAddDel(CloudScriptExecutionCompleteDelegates); }
|
|
function ClearOnCloudScriptExecutionCompleteDelegate( delegate<OnCloudScriptExecutionComplete> InDelegate ) { `FillClearDel(CloudScriptExecutionCompleteDelegates); }
|
|
|
|
|
|
function bool IsRegisteredWithPlayfab()
|
|
{
|
|
return CachedLobbyId != "";
|
|
}
|
|
|
|
|
|
function string GetCachedLobbyId()
|
|
{
|
|
return CachedLobbyId;
|
|
}
|
|
|
|
|
|
event bool IsCloudServer()
|
|
{
|
|
return bCloudServer;
|
|
}
|
|
|
|
|
|
event string GetServerId()
|
|
{
|
|
return CachedServerId;
|
|
}
|
|
|
|
|
|
function int GetIndexForCurrentRegion()
|
|
{
|
|
local int i;
|
|
|
|
for( i = 0; i < KnownRegions.Length; i++ )
|
|
{
|
|
if( KnownRegions[i].Name == CurrRegionName )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
`warn("Failed to find index for current region"@CurrRegionName);
|
|
return -1;
|
|
}
|
|
|
|
|
|
function SetIndexForCurrentRegion( int InRegionIndex )
|
|
{
|
|
if( InRegionIndex >= 0 && InRegionIndex < KnownRegions.Length )
|
|
{
|
|
SetDefaultRegion(KnownRegions[InRegionIndex].Name);
|
|
}
|
|
else
|
|
{
|
|
`warn("Failed to set region index"@InRegionIndex);
|
|
}
|
|
}
|
|
|
|
|
|
static function array<string> GetLocalizedRegionList()
|
|
{
|
|
local int i;
|
|
local array<string> LocalizedRegions;
|
|
|
|
for( i = 0; i < default.KnownRegions.Length; i++ )
|
|
{
|
|
LocalizedRegions.AddItem( Localize( "Regions", default.KnownRegions[i].Name, "KFGameConsole" ) );
|
|
}
|
|
|
|
return LocalizedRegions;
|
|
}
|
|
|
|
static function string GetLocalizedRegionName(int RegionIndex)
|
|
{
|
|
return Localize( "Regions", default.KnownRegions[RegionIndex].Name, "KFGameConsole" );
|
|
}
|
|
|
|
|
|
event OnlineProfileSettings GetProfileSettings( byte LocalUserNum )
|
|
{
|
|
return class'GameEngine'.static.GetOnlineSubsystem().PlayerInterface.GetProfileSettings( LocalUserNum );
|
|
}
|
|
|
|
|
|
|
|
// Server API calls
|
|
/////////////////////////////////////////////////////////////////////////
|
|
native function ServerValidatePlayer( const string ClientAuthTicket );
|
|
native function ServerNotifyPlayerJoined( const string PlayfabId );
|
|
native function ServerNotifyPlayerLeft( const string PlayfabId );
|
|
native function ServerUpdateOnlineGame();
|
|
native function ServerRegisterGame();
|
|
native function ServerSetOpenStatus( const bool bOpen );
|
|
native function ServerSetSteamServerUID(const qword UID);
|
|
|
|
native function ServerUpdateInternalUserData( const string ForPlayerId, array<string> InKeys, array<string> InValues );
|
|
native function ServerRetrieveInternalUserData( const string ForPlayerId, array<string> InKeys );
|
|
native function ServerAddVirtualCurrencyForUser( const string ForPlayerId, const int AmountToAdd, optional string CurrencyName = "GM" );
|
|
native function ServerRemoveVirtualCurrencyForUser( const string ForPlayerId, const int AmountToRemove, optional string CurrencyName = "GM" );
|
|
native function ServerGrantItemsForUser( const string ForPlayerId, array<string> ItemIds );
|
|
|
|
native function ServerAllocate();
|
|
native function ServerDeallocate( optional bool bForce );
|
|
|
|
function CreateGameSettings( class<OnlineGameSettings> GameSettingsClass )
|
|
{
|
|
if( CachedGameSettings == none )
|
|
{
|
|
CachedGameSettings = new GameSettingsClass;
|
|
}
|
|
}
|
|
|
|
event OnlineGameSettings GetGameSettings()
|
|
{
|
|
return CachedGameSettings;
|
|
}
|
|
|
|
|
|
// Private calls
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Auths with online service (ex. PSN). Calls into OSS to do this
|
|
private event AuthWithOnlineService( byte LocalUserNum, string ForURL )
|
|
{
|
|
local OnlineSubsystem OSS;
|
|
|
|
OSS = class'GameEngine'.static.GetOnlineSubsystem();
|
|
if( OSS != none && OSS.PlayerInterface != none )
|
|
{
|
|
OSS.PlayerInterface.AddURLTokenRetrievedDelegate( LocalUserNum, OnTokenAndSignatureRetrieved );
|
|
OSS.PlayerInterface.GetTokenAndSignatureForURL( LocalUserNum, ForURL );
|
|
}
|
|
}
|
|
|
|
private function OnTokenAndSignatureRetrieved(byte LocalUserNum, string URL, string Token, string Signature)
|
|
{
|
|
class'GameEngine'.static.GetOnlineSubsystem().PlayerInterface.ClearURLTokenRetrievedDelegate(LocalUserNum, OnTokenAndSignatureRetrieved);
|
|
OnlineServiceAuthComplete( URL, Token, Signature );
|
|
}
|
|
|
|
|
|
// The rest is handled in native
|
|
private native function OnlineServiceAuthComplete( string ForURL, string Token, string Signature );
|
|
|
|
|
|
cpptext
|
|
{
|
|
virtual void Initialize();
|
|
|
|
virtual UBOOL IsTickable() const
|
|
{
|
|
// We cannot tick objects that are unreachable or are in the process of being loaded in the background.
|
|
return !HasAnyFlags( RF_Unreachable | RF_AsyncLoading );
|
|
}
|
|
|
|
virtual UBOOL IsTickableWhenPaused() const
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
virtual void Tick( FLOAT DeltaSeconds );
|
|
|
|
virtual void Shutdown();
|
|
|
|
UBOOL WasLaunchedByPlayfab() { return bLaunchedByPlayfab; }
|
|
|
|
virtual FString GetLobbyId() { return CachedLobbyId; }
|
|
virtual void SetLobbyId( const FString& InLobbyId ) { CachedLobbyId = InLobbyId; }
|
|
|
|
// Notification from OSS after entitlements have been read
|
|
virtual void OnEntitlementsRead();
|
|
|
|
// Called on the event inventory is updated
|
|
virtual void InventoryUpdated( TArray<FCurrentInventoryEntry>& NewInvList );
|
|
|
|
// Adds durable entitlements to inventory list
|
|
virtual void AddDurableEntitlementsToInventory( TArray<FCurrentInventoryEntry>& InvList );
|
|
|
|
// Sets a timer to attempt registration again
|
|
virtual void Reregister();
|
|
|
|
// Retrieves the catalog name
|
|
virtual FString GetCatalogName() { return CatalogName; }
|
|
}
|
|
|
|
|
|
defaultproperties
|
|
{
|
|
CurrRegionName=""
|
|
// Auth refreshed every hour
|
|
SecondsForAuthRefreshTime=3600
|
|
// 60 seconds for every heartbeat
|
|
HeartbeatInterval=60.0
|
|
DeallocateTimeUpdateInterval=30.0
|
|
PlayfabNPServiceLabel=1
|
|
ReregisterInterval=10.0
|
|
MaxRetryLoginAttempts=3
|
|
VerifyCertificateTime=600.0
|
|
}
|