1
0
KF2-Dev-Scripts/Engine/Classes/LocalPlayer.uc
2020-12-13 18:01:13 +03:00

761 lines
25 KiB
Ucode

//=============================================================================
// LocalPlayer
// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
//=============================================================================
class LocalPlayer extends Player
within Engine
config(Engine)
inherits(FObserverInterface)
native
transient;
/** The controller ID which this player accepts input from. */
var int ControllerId;
/** The master viewport containing this player's view. */
var GameViewportClient ViewportClient;
/** The coordinates for the upper left corner of the master viewport subregion allocated to this player. 0-1 */
var vector2d Origin;
/** The size of the master viewport subregion allocated to this player. 0-1 */
var vector2d Size;
/** Chain of post process effects for this player view */
var transient const PostProcessChain PlayerPostProcess;
var transient const array<PostProcessChain> PlayerPostProcessChains;
/** This gets set when we don't want to use the player chain and use the world/default chain instead */
var transient bool bForceDefaultPostProcessChain;
var private native const pointer ViewState{FSceneViewStateInterface};
// WITH_REALD BEGIN
var private native const pointer ViewState2{FSceneViewStateInterface};
// WITH_REALD END
struct SynchronizedActorVisibilityHistory
{
var pointer State;
var pointer CriticalSection;
};
var private native transient const SynchronizedActorVisibilityHistory ActorVisibilityHistory;
/** The location of the player's view the previous frame. */
var const transient vector LastViewLocation;
struct native CurrentPostProcessVolumeInfo
{
/** Last pp settings used when blending to the next set of volume values. */
var PostProcessSettings LastSettings;
/** The last post process volume that was applied to the scene */
var PostProcessVolume LastVolumeUsed;
/** Time when a new post process volume was set */
var float BlendStartTime;
/** Time when the settings blend was last updated. */
var float LastBlendTime;
};
/** The Post Process value used */
var const noimport transient CurrentPostProcessVolumeInfo CurrentPPInfo;
/** Baseline Level Post Process Info */
var const noimport transient CurrentPostProcessVolumeInfo LevelPPInfo;
struct native PostProcessSettingsOverride
{
var PostProcessSettings Settings;
var bool bBlendingIn;
var bool bBlendingOut;
var float CurrentBlendInTime; // blend-in progress, in seconds
var float CurrentBlendOutTime; // blend-out progress, in seconds
var float BlendInDuration; // total time of current blend-in
var float BlendOutDuration; // total time of current blend-out
var float BlendStartTime; // time this override became active, for blending internal to Settings
var InterpCurveFloat TimeAlphaCurve; // Curve to map time with blend alpha. Optional, will override BlendInDuration/BlendOutDuration
};
/** Stack of active overrides. Restricting this to 1 "active" and have all others be fading out, though
* it should be fairly easy to extend to allow gameplay to maintain multiple actives at once. */
var protected transient array<PostProcessSettingsOverride> ActivePPOverrides;
/** How to constrain perspective viewport FOV */
var config EAspectRatioAxisConstraint AspectRatioAxisConstraint;
/** The last map this player remembers being on. Used to determine if the map has changed and the pp needs to be reset to default*/
var string LastMap;
/** Whether or not to use the next map's defaults and ditch the current pp settings */
var bool bWantToResetToMapDefaultPP;
/** set when we've sent a split join request */
var const editconst transient bool bSentSplitJoin;
/** This Local Player's translation context. See GetTranslationContext() below. */
var TranslationContext TagContext;
/** Caches a local reference to the online subsystems auth interface, if it has one set */
var OnlineAuthInterface CachedAuthInt;
/** Whether or not we are awaiting server auth results */
var bool bPendingServerAuth;
/** Timestamp for when server auth started */
var float ServerAuthTimestamp;
/** If this many seconds pass before server auth completes, 'ServerAuthTimedOut' is triggered (from native code) */
var int ServerAuthTimeout;
/** The number of times server authentication has failed */
var int ServerAuthRetryCount;
/** The maximum number of server auth retries */
var int MaxServerAuthRetryCount;
/** Stores the UID of the server currently being authenticated */
var UniqueNetId ServerAuthUID;
cpptext
{
/** Is object propagation currently overriding our view? */
static UBOOL bOverrideView;
static FVector OverrideLocation;
static FRotator OverrideRotation;
// Constructor.
ULocalPlayer();
/**
* Tick tasks required for auth code
*
* @param DeltaTime The time passed since the last tick
*/
virtual void Tick(FLOAT DeltaTime);
/**
* Rebuilds the PlayerPostProcessChain.
* This should be called whenever the chain array has items inserted/removed.
*/
void RebuildPlayerPostProcessChain();
/**
* Updates the post-process settings for the player's view.
* @param ViewLocation - The player's current view location.
*/
virtual void UpdatePostProcessSettings(const FVector& ViewLocation);
/** Update a specific CurrentPostProcessVolumeInfo with the settings and volume specified
*
* @param PPInfo - The CurrentPostProcessVolumeInfo struct to update
* @param NewSettings - The PostProcessSettings to apply to PPInfo
* @param NewVolume - The PostProcessVolume to apply to PPInfo
*/
virtual void UpdatePPSetting(FCurrentPostProcessVolumeInfo& PPVolume, FPostProcessSettings& NewSettings, const FLOAT CurrentWorldTime);
#if WITH_REALD
FSceneView* CalcSceneViewOffs( FSceneViewFamily* ViewFamily, FVector& ViewLocation, FRotator& ViewRotation, FViewport* Viewport, FMatrix* Offset=NULL, FViewElementDrawer* ViewDrawer=NULL );
#endif
/**
* Calculate the view settings for drawing from this view actor
*
* @param View - output view struct
* @param ViewLocation - output actor location
* @param ViewRotation - output actor rotation
* @param Viewport - current client viewport
* @param ViewDrawer - optional drawing in the view
*/
FSceneView* CalcSceneView( FSceneViewFamily* ViewFamily, FVector& ViewLocation, FRotator& ViewRotation, FViewport* Viewport, FViewElementDrawer* ViewDrawer=NULL );
// UObject interface.
virtual void FinishDestroy();
// FExec interface.
virtual UBOOL Exec(const TCHAR* Cmd,FOutputDevice& Ar);
void ExecMacro( const TCHAR* Filename, FOutputDevice& Ar );
// FObserverInterface interface
virtual FVector GetObserverViewLocation()
{
return LastViewLocation;
}
}
/**
* Creates an actor for this player.
* @param URL - The URL the player joined with.
* @param OutError - If an error occurred, returns the error description.
* @return False if an error occurred, true if the play actor was successfully spawned.
*/
native final function bool SpawnPlayActor(string URL,out string OutError);
/** sends a splitscreen join command to the server to allow a splitscreen player to connect to the game
* the client must already be connected to a server for this function to work
* @note this happens automatically for all viewports that exist during the initial server connect
* so it's only necessary to manually call this for viewports created after that
* if the join fails (because the server was full, for example) all viewports on this client will be disconnected
*/
native final function SendSplitJoin();
/**
* Tests the visibility state of an actor in the most recent frame of this player's view to complete rendering.
* @param TestActor - The actor to check visibility for.
* @return True if the actor was visible in the frame.
*/
native final function bool GetActorVisibility(Actor TestActor) const;
/**
* Begins an override of the current post process settings.
*/
simulated native function OverridePostProcessSettings( PostProcessSettings OverrideSettings, optional float BlendInTime );
/**
* Begins an override of the current post process settings with a time/alpha curve.
*/
simulated native function OverridePostProcessSettingsCurve( PostProcessSettings OverrideSettings, const out InterpCurveFloat Curve);
/**
* Stop overriding post process settings.
* Will only affect active overrides -- in-progress blendouts are unaffected.
* @param BlendOutTime - The amount of time you want to take to recover from the override you are clearing.
*/
simulated native function ClearPostProcessSettingsOverride(optional float BlendOutTime);
/**
* Changes the ControllerId for this player; if the specified ControllerId is already taken by another player, changes the ControllerId
* for the other player to the ControllerId currently in use by this player.
*
* @param NewControllerId the ControllerId to assign to this player.
*/
final function SetControllerId( int NewControllerId )
{
local LocalPlayer OtherPlayer;
local int CurrentControllerId;
if ( ControllerId != NewControllerId )
{
`log(Name @ "changing ControllerId from" @ ControllerId @ "to" @ NewControllerId,,'PlayerManagement');
// first, unregister the player's data stores if we already have a PlayerController.
if ( Actor != None )
{
Actor.PreControllerIdChange();
}
CurrentControllerId = ControllerId;
// set this player's ControllerId to -1 so that if we need to swap controllerIds with another player we don't
// re-enter the function for this player.
ControllerId = -1;
// see if another player is already using this ControllerId; if so, swap controllerIds with them
OtherPlayer = ViewportClient.FindPlayerByControllerId(NewControllerId);
if ( OtherPlayer != None )
{
OtherPlayer.SetControllerId(CurrentControllerId);
}
ControllerId = NewControllerId;
if ( Actor != None )
{
Actor.PostControllerIdChange();
}
}
}
/**
* A TranslationContext is part of the system for managing translation tags in localization text.
* This system handles text with special tags. E.g.: Press <Controller:GBA_POI/> to look at point of interest.
* A TranslationContext provides information that cannot be deduced from the text alone.
* In this case, it is used to differentiate between players 1 and 2.
* @return Translation Context for this Local Player.
*/
native final function TranslationContext GetTranslationContext();
/**
* Add the given post process chain to the chain at the given index.
*
* @param InChain The post process chain to insert.
* @param InIndex The position to insert the chain in the complete chain.
* If -1, insert it at the end of the chain.
* @param bInClone If TRUE, create a deep copy of the chains effects before insertion.
*
* @return boolean TRUE if the chain was inserted
* FALSE if not
*/
native function bool InsertPostProcessingChain(PostProcessChain InChain, int InIndex, bool bInClone);
/**
* Remove the post process chain at the given index.
*
* @param InIndex The position to insert the chain in the complete chain.
*
* @return boolean TRUE if the chain was removed
* FALSE if not
*/
native function bool RemovePostProcessingChain(int InIndex);
/**
* Remove all post process chains.
*
* @return boolean TRUE if the chain array was cleared
* FALSE if not
*/
native function bool RemoveAllPostProcessingChains();
/**
* Get the PPChain at the given index.
*
* @param InIndex The index of the chain to retrieve.
*
* @return PostProcessChain The post process chain if found; NULL if not.
*/
native function PostProcessChain GetPostProcessChain(int InIndex);
/**
* Forces the PlayerPostProcess chain to be rebuilt.
* This should be called if a PPChain is retrieved using the GetPostProcessChain,
* and is modified directly.
*/
native function TouchPlayerPostProcessChain();
/** transforms 2D screen coordinates into a 3D world-space origin and direction
* @note: use the Canvas version where possible as it already has the necessary information,
* whereas this function must gather it and is therefore slower
* @param ScreenPos - relative screen coordinates (0 to 1, relative to this player's viewport region)
* @param WorldOrigin (out) - world-space origin vector
* @param WorldDirection (out) - world-space direction vector
*/
native final function DeProject(vector2D RelativeScreenPos, out vector WorldOrigin, out vector WorldDirection);
/** transforms 3D world coordinates into a 2D screen position (0-1, 0-1)
* @note: use the Canvas version where possible as it already has the necessary information,
* whereas this function must gather it and is therefore slower
* @param WorldLoc - world location to project
* @return screen coordinates (0-1, 0-1)
*/
native final function vector2d Project(vector WorldLoc);
/** transforms 2D screen coordinates into a 3D world-space origin and direction
* @note: use the Canvas version where possible as it already has the necessary information,
* whereas this function must gather it and is therefore slower
* @note: this version does not update visibility lists, physics world camera, or anything else
* that the normal DeProject does. it doesn't call CalcSceneView.
* @param ScreenPos - relative screen coordinates (0 to 1, relative to this player's viewport region)
* @param WorldOrigin (out) - world-space origin vector
* @param WorldDirection (out) - world-space direction vector
*/
native final function FastDeProject(vector2D RelativeScreenPos, out vector WorldOrigin, out vector WorldDirection);
/** transforms 3D world coordinates into a 2D screen position (0-1, 0-1)
* @note: use the Canvas version where possible as it already has the necessary information,
* whereas this function must gather it and is therefore slower
* @note: this version does not update visibility lists, physics world camera, or anything else
* that the normal Project does. it doesn't call CalcSceneView.
* @param WorldLoc - world location to project
* @return screen coordinates (0-1, 0-1)
*/
native final function vector2d FastProject(vector WorldLoc);
/** retrieves this player's unique net ID from the online subsystem */
final event UniqueNetId GetUniqueNetId()
{
local UniqueNetId Result;
local GameEngine TheEngine;
TheEngine = GameEngine(Outer);
if (TheEngine != None && TheEngine.OnlineSubsystem != None && TheEngine.OnlineSubsystem.PlayerInterface != None)
{
TheEngine.OnlineSubsystem.PlayerInterface.GetUniquePlayerId(ControllerId, Result);
}
return Result;
}
/** retrieves this player's name/tag from the online subsytem
* if this function returns a non-empty string, the returned name will replace the "Name" URL parameter
* passed around in the level loading and connection code, which normally comes from DefaultEngine.ini
*/
event string GetNickname()
{
local GameEngine TheEngine;
TheEngine = GameEngine(Outer);
if (TheEngine != None && TheEngine.OnlineSubsystem != None && TheEngine.OnlineSubsystem.PlayerInterface != None)
{
return TheEngine.OnlineSubsystem .PlayerInterface.GetPlayerNickname(ControllerId);
}
else
{
return "";
}
}
/**
* Authentication handling
*/
/**
* Triggered when the client opens a connection to a server, in order to setup authentication delegates
*/
event NotifyServerConnectionOpen()
{
local WorldInfo WI;
// Currently, only the primary local player supports auth code
if (GamePlayers[0] == self)
{
// Setup the online subsystem delegates
CachedAuthInt = Class'GameEngine'.static.GetOnlineSubsystem().AuthInterface;
if (CachedAuthInt != none)
{
CachedAuthInt.AddClientAuthRequestDelegate(ProcessClientAuthRequest);
CachedAuthInt.AddServerAuthResponseDelegate(ProcessServerAuthResponse);
CachedAuthInt.AddServerAuthCompleteDelegate(OnServerAuthComplete);
CachedAuthInt.AddClientAuthEndSessionRequestDelegate(ProcessClientAuthEndSessionRequest);
CachedAuthInt.AddServerConnectionCloseDelegate(OnServerConnectionClose);
}
// Execute server auth tracking, no matter what the server auth configuration is
// (just so the clientside code can implement strict checks, if desired)
bPendingServerAuth = true;
WI = Class'WorldInfo'.static.GetWorldInfo();
if (WI != none)
{
ServerAuthTimestamp = WI.RealTimeSeconds;
}
else
{
// If WorldInfo does not exist, the native code will set ServerAuthTimestamp when it is created (if > RealTimeSeconds)
ServerAuthTimestamp = 10.0;
}
}
}
/**
* Client authentication handling
*/
/**
* Called when the client receives a message from the server, requesting a client auth session
*
* @param ServerUID The UID of the game server
* @param ServerIP The public (external) IP of the game server
* @param ServerPort The port of the game server
* @param bSecure whether or not the server has anticheat enabled (relevant to OnlineSubsystemSteamworks and VAC)
*/
//@HSL_BEGIN_XBOX
function ProcessClientAuthRequest(UniqueNetId ServerUID, IpAddr ServerIP, int ServerPort, bool bSecure)
//@HSL_END_XBOX
{
local UniqueNetId NullId;
local int AuthTicketUID;
if (ServerUID != NullId)
{
if (CachedAuthInt.CreateClientAuthSession(ServerUID, ServerIP, ServerPort, bSecure, AuthTicketUID))
{
if (!class'WorldInfo'.static.isEOSBuild() && !CachedAuthInt.SendClientAuthResponse(AuthTicketUID))
{
`log("LocalPlayer::ProcessClientAuthRequest: WARNING!!! Failed to send auth ticket to server");
}
}
else
{
`log("LocalPlayer::ProcessClientAuthRequest: WARNING!!! Failed to create client auth session");
}
}
}
/**
* Called when the client receives a request from the server, to end an active auth session
*
* @param ServerConnection The server NetConnection
*/
function ProcessClientAuthEndSessionRequest(Player ServerConnection)
{
local LocalAuthSession CurClientSession;
local AuthSession CurServerSession;
if (CachedAuthInt.FindLocalClientAuthSession(ServerConnection, CurClientSession))
{
CachedAuthInt.EndLocalClientAuthSession(CurClientSession.EndPointUID, CurClientSession.EndPointIP, CurClientSession.EndPointPort);
}
else
{
`log("LocalPlayer::ProcessClientAuthEndSessionRequest: Couldn't find local client auth session");
}
if (CachedAuthInt.FindServerAuthSession(ServerConnection, CurServerSession))
{
CachedAuthInt.EndRemoteServerAuthSession(CurServerSession.EndPointUID, CurServerSession.EndPointIP);
}
else
{
`log("LocalPlayer::ProcessClientAuthEndSessionRequest: Couldn't find server auth session");
}
}
/**
* Server authentication handling
*/
/**
* Called when the client receives auth data from the server, needed for authentication
*
* @param ServerUID The UID of the server
* @param ServerIP The IP of the server
* @param AuthTicketUID The UID used to reference the auth data
*/
//@HSL_BEGIN_XBOX
function ProcessServerAuthResponse(UniqueNetId ServerUID, IpAddr ServerIP, int AuthTicketUID)
//@HSL_END_XBOX
{
local WorldInfo WI;
if (CachedAuthInt.VerifyServerAuthSession(ServerUID, ServerIP, AuthTicketUID))
{
bPendingServerAuth = True;
ServerAuthUID = ServerUID;
WI = Class'WorldInfo'.static.GetWorldInfo();
if (WI != none)
{
ServerAuthTimestamp = WI.RealTimeSeconds;
}
else
{
// If WorldInfo does not exist, the native code will set ServerAuthTimestamp when it is created (if > RealTimeSeconds)
ServerAuthTimestamp = 10.0;
}
`log("Kicked off game server auth");
}
else
{
`log("Failed to kickoff game server auth");
}
}
/**
* Called on the client, when the authentication result for the server has returned
*
* @param bSuccess whether or not authentication was successful
* @param ServerUID The UID of the server
* @param ServerConnection The connection associated with the server (for retrieving auth session data)
* @param ExtraInfo Extra information about authentication, e.g. failure reasons
*/
function OnServerAuthComplete(bool bSuccess, UniqueNetId ServerUID, Player ServerConnection, string ExtraInfo)
{
if (bSuccess)
{
`log("Server auth success");
bPendingServerAuth = False;
}
else
{
// Retry auth
ServerAuthTimedOut();
}
}
/**
* Triggered by native code, if server auth times out
* NOTE: Determined by: (WorldInfo.RealTimeSeconds - ServerAuthTimestamp) > ServerAuthTimeout
*/
event ServerAuthTimedOut()
{
local WorldInfo WI;
local AuthSession CurServerSession;
if (CachedAuthInt != none)
{
if (ServerAuthRetryCount < MaxServerAuthRetryCount)
{
// End the current server auth session, before retrying
foreach CachedAuthInt.AllServerAuthSessions(CurServerSession)
{
if (CurServerSession.EndPointUID == ServerAuthUID)
{
CachedAuthInt.EndRemoteServerAuthSession(CurServerSession.EndPointUID, CurServerSession.EndPointIP);
break;
}
}
`log("Sending server auth retry request");
// Send a retry request
CachedAuthInt.SendServerAuthRetryRequest();
ServerAuthRetryCount++;
// Update the auth timestamp
WI = Class'WorldInfo'.static.GetWorldInfo();
if (WI != none)
{
ServerAuthTimestamp = WI.RealTimeSeconds;
}
else
{
ServerAuthTimestamp = 10.0;
}
}
else
{
ServerAuthFailure();
}
}
}
/**
* Called when server authentication fails completely, after several retries.
* If strict handling of server auth is required (e.g. disconnecting the client), implement it here
*/
function ServerAuthFailure()
{
`log("Server authentication failed after"@MaxServerAuthRetryCount@"tries");
// Uncomment to enable strict authentication checks
//Actor.ConsoleCommand("Disconnect");
}
/**
* Server disconnect cleanup
*/
/**
* Called on the client when a server net connection is closing (so auth sessions can be ended)
* NOTE: Triggered >before< NotifyServerConnectionClose
*
* @param ServerConnection The server NetConnection that is closing
*/
function OnServerConnectionClose(Player ServerConnection)
{
// Pass on to the static function, to keep code in one place
StaticOnServerConnectionClose(ServerConnection);
}
/**
* Static version of the above, to be called when there is no valid LocalPlayer instance (e.g. at exit)
*
* @param ServerConnection The server NetConnection that is closing
*/
static final function StaticOnServerConnectionClose(Player ServerConnection)
{
local OnlineAuthInterface CurAuthInt;
local LocalAuthSession CurClientSession;
local AuthSession CurServerSession;
CurAuthInt = Class'GameEngine'.static.GetOnlineSubsystem().AuthInterface;
if (CurAuthInt != none)
{
if (CurAuthInt.FindLocalClientAuthSession(ServerConnection, CurClientSession))
{
CurAuthInt.EndLocalClientAuthSession(CurClientSession.EndPointUID, CurClientSession.EndPointIP,
CurClientSession.EndPointPort);
}
else
{
`log("LocalPlayer::StaticOnServerConnectionClose: Couldn't find local client auth session");
}
if (CurAuthInt.FindServerAuthSession(ServerConnection, CurServerSession))
{
CurAuthInt.EndRemoteServerAuthSession(CurServerSession.EndPointUID, CurServerSession.EndPointIP);
}
else
{
`log("LocalPlayer::StaticOnServerConnectionClose: Couldn't find server auth session");
}
}
}
/**
* Exit cleanup
*/
/**
* Triggered when the viewport associated with this LocalPlayer has been closed, and the LocalPlayer is about to become invalid
* NOTE: This usually happens just before game exit, by clicking the window close button for the game
*/
event ViewportClosed()
{
Cleanup(True);
}
/**
* Triggered when the client closes the connection to the server, for cleaning up authentication delegates
*/
event NotifyServerConnectionClose()
{
Cleanup();
}
/**
* Trigered by the game engine upon exit, for online subsystem cleanup
*/
event Exit()
{
// Trigger regular cleanup
Cleanup(True);
}
/**
* Cleans up online subsystem delegates upon server disconnect, or game exit
*
* @param bExit whether or not cleanup was triggered due to game exit
*/
function Cleanup(optional bool bExit)
{
// Currently, only the primary local player supports auth code
if (GamePlayers[0] == self)
{
// Clear online subsystem delegates
if (CachedAuthInt != none)
{
CachedAuthInt.ClearClientAuthRequestDelegate(ProcessClientAuthRequest);
CachedAuthInt.ClearServerAuthResponseDelegate(ProcessServerAuthResponse);
CachedAuthInt.ClearServerAuthCompleteDelegate(OnServerAuthComplete);
CachedAuthInt.ClearClientAuthEndSessionRequestDelegate(ProcessClientAuthEndSessionRequest);
CachedAuthInt.ClearServerConnectionCloseDelegate(OnServerConnectionClose);
if (bExit)
{
// End local client auth sessions
CachedAuthInt.EndAllLocalClientAuthSessions();
// End server auth sessions
CachedAuthInt.EndAllRemoteServerAuthSessions();
}
}
CachedAuthInt = none;
bPendingServerAuth = False;
}
}
defaultproperties
{
// bOverridePostProcessSettings=false
// inital postprocess setting should be set, not faded in
bWantToResetToMapDefaultPP=true
bForceDefaultPostProcessChain=false
ServerAuthTimeout=10
MaxServerAuthRetryCount=3
}