When changing the APlayerController’s state to NAME_Spectating then every PlayerTick() the client calls:
void APlayerController::SafeServerUpdateSpectatorState()
{
if (IsInState(NAME_Spectating))
{
if (GetWorld()->TimeSince(LastSpectatorStateSynchTime) > RetryServerCheckSpectatorThrottleTime)
{
ServerSetSpectatorLocation(GetFocalLocation());
LastSpectatorStateSynchTime = GetWorld()->TimeSeconds;
}
}
}
If the client then is in NAME_Spectating state and some amount of time has passed it calls a function on the server:
void APlayerController::ServerSetSpectatorLocation_Implementation(FVector NewLoc)
{
if ( IsInState(NAME_Spectating) )
{
if ( GetWorld()->TimeSeconds - LastSpectatorStateSynchTime > 2.f )
{
ClientGotoState(GetStateName());
LastSpectatorStateSynchTime = GetWorld()->TimeSeconds;
}
}
// if we receive this with !bIsSpectating, the client is in the wrong state; tell it what state it should be in
else if (GetWorld()->TimeSeconds != LastSpectatorStateSynchTime)
{
.... // left out since not important for question
}
}
This function on the server every two seconds calls ClientGotoState(GetStateName());. StateName is of course NAME_Spectating.
Conclusively, Client calls server function when in a certain state. This server function tells the client to be in exactly that state.
Loop?
I don’t understand the sense behind this.