void UPendingNetGame::InitNetDriver() { if (!GDisallowNetworkTravel) { NETWORK_PROFILER(GNetworkProfiler.TrackSessionChange(true, URL)); // Try to create network driver. if (GEngine->CreateNamedNetDriver(this, NAME_PendingNetDriver, NAME_GameNetDriver)) { NetDriver = GEngine->FindNamedNetDriver(this, NAME_PendingNetDriver); } check(NetDriver); if( NetDriver->InitConnect( this, URL, ConnectionError ) ) { UNetConnection* ServerConn = NetDriver->ServerConnection; // Kick off the connection handshake if (ServerConn->StatelessConnectComponent.IsValid()) { ServerConn->StatelessConnectComponent.Pin()->SendInitialConnect(); } // Send initial message. uint8 IsLittleEndian = uint8(PLATFORM_LITTLE_ENDIAN); check(IsLittleEndian == !!IsLittleEndian); // should only be one or zero uint32 LocalNetworkVersion = FNetworkVersion::GetLocalNetworkVersion(); FNetControlMessage<NMT_Hello>::Send(ServerConn, IsLittleEndian, LocalNetworkVersion); ServerConn->FlushNet(); } else { // error initializing the network stack... UE_LOG(LogNet, Warning, TEXT("error initializing the network stack")); GEngine->DestroyNamedNetDriver(this, NetDriver->NetDriverName); NetDriver = NULL; // ConnectionError should be set by calling InitConnect...however, if we set NetDriver to NULL without setting a // value for ConnectionError, we'll trigger the assertion at the top of UPendingNetGame::Tick() so make sure it's set if ( ConnectionError.Len() == 0 ) { ConnectionError = NSLOCTEXT("Engine", "NetworkInit", "Error initializing network layer.").ToString(); } } } else { ConnectionError = NSLOCTEXT("Engine", "UsedCheatCommands", "Console commands were used which are disallowed in netplay. You must restart the game to create a match.").ToString(); } }
void AOnlineBeaconHost::DisconnectClient(AOnlineBeaconClient* ClientActor) { if (ClientActor && ClientActor->GetConnectionState() != EBeaconConnectionState::Closed && !ClientActor->IsPendingKill()) { ClientActor->SetConnectionState(EBeaconConnectionState::Closed); UNetConnection* Connection = ClientActor->GetNetConnection(); UE_LOG(LogBeacon, Log, TEXT("DisconnectClient for %s. UNetConnection %s UNetDriver %s State %d"), *GetNameSafe(ClientActor), *GetNameSafe(Connection), Connection ? *GetNameSafe(Connection->Driver) : TEXT("null"), Connection ? Connection->State : -1); // Closing the connection will start the chain of events leading to the removal from lists and destruction of the actor if (Connection && Connection->State != USOCK_Closed) { Connection->FlushNet(true); Connection->Close(); } } }
void ANUTActor::NetFlush() { UNetDriver* CurNetDriver = GetNetDriver(); if (CurNetDriver != NULL) { UNetConnection* ServerConn = CurNetDriver->ServerConnection; if (ServerConn != NULL) { UE_LOG(LogUnitTest, Log, TEXT("Flushing ServerConnection")); ServerConn->FlushNet(); } else { UE_LOG(LogUnitTest, Log, TEXT("Flushing ClientConnections")); for (auto CurConn : CurNetDriver->ClientConnections) { CurConn->FlushNet(); } } } }
void UGameEngine::Tick( float DeltaSeconds, bool bIdleMode ) { SCOPE_CYCLE_COUNTER(STAT_GameEngineTick); NETWORK_PROFILER(GNetworkProfiler.TrackFrameBegin()); int32 LocalTickCycles=0; CLOCK_CYCLES(LocalTickCycles); // ----------------------------------------------------- // Non-World related stuff // ----------------------------------------------------- if( DeltaSeconds < 0.0f ) { #if (UE_BUILD_SHIPPING && WITH_EDITOR) // End users don't have access to the secure parts of UDN. Regardless, they won't // need the warning because the game ships with AMD drivers that address the issue. UE_LOG(LogEngine, Fatal,TEXT("Negative delta time!")); #else // Send developers to the support list thread. UE_LOG(LogEngine, Fatal,TEXT("Negative delta time! Please see https://udn.epicgames.com/lists/showpost.php?list=ue3bugs&id=4364")); #endif } // Tick allocator if( GMalloc != NULL ) { GMalloc->Tick( DeltaSeconds ); } // Tick the module manager FModuleManager::Get().Tick(); if (!IsRunningDedicatedServer() && !IsRunningCommandlet()) { // Clean up the game viewports that have been closed. CleanupGameViewport(); } // If all viewports closed, time to exit. if(GIsClient && GameViewport == NULL ) { UE_LOG(LogEngine, Log, TEXT("All Windows Closed") ); FPlatformMisc::RequestExit( 0 ); return; } if ( GameViewport != NULL ) { // Decide whether to drop high detail because of frame rate. GameViewport->SetDropDetail(DeltaSeconds); } // Update subsystems. { // This assumes that UObject::StaticTick only calls ProcessAsyncLoading. StaticTick( DeltaSeconds ); } // ----------------------------------------------------- // Begin ticking worlds // ----------------------------------------------------- int32 OriginalGWorldContext = INDEX_NONE; for (int32 i=0; i < WorldList.Num(); ++i) { if (WorldList[i].World() == GWorld) { OriginalGWorldContext = WorldList[i].ContextHandle; break; } } bool WorldWasPaused = false; for (int32 WorldIdx = 0; WorldIdx < WorldList.Num(); ++WorldIdx) { FWorldContext &Context = WorldList[WorldIdx]; if (Context.World() == NULL) { continue; } WorldWasPaused |= Context.World()->IsPaused(); GWorld = Context.World(); // Tick all travel and Pending NetGames (Seamless, server, client) TickWorldTravel(Context, DeltaSeconds); if (!IsRunningDedicatedServer() && !IsRunningCommandlet()) { // Only update reflection captures in game once all 'always loaded' levels have been loaded // This won't work with actual level streaming though if (Context.World()->AreAlwaysLoadedLevelsLoaded()) { // Update sky light first because it's considered direct lighting, sky diffuse will be visible in reflection capture indirect specular USkyLightComponent::UpdateSkyCaptureContents(Context.World()); UReflectionCaptureComponent::UpdateReflectionCaptureContents(Context.World()); } } if (!bIdleMode) { // Tick the world. GameCycles=0; CLOCK_CYCLES(GameCycles); Context.World()->Tick( LEVELTICK_All, DeltaSeconds ); UNCLOCK_CYCLES(GameCycles); } // Issue cause event after first tick to provide a chance for the game to spawn the player and such. if( Context.World()->bWorldWasLoadedThisTick ) { Context.World()->bWorldWasLoadedThisTick = false; const TCHAR* InitialExec = Context.LastURL.GetOption(TEXT("causeevent="),NULL); ULocalPlayer* GamePlayer = Context.GamePlayers.Num() > 0 ? Context.GamePlayers[0] : NULL; if( InitialExec && GamePlayer ) { UE_LOG(LogEngine, Log, TEXT("Issuing initial cause event passed from URL: %s"), InitialExec); GamePlayer->Exec( GamePlayer->GetWorld(), *(FString("CAUSEEVENT ") + InitialExec), *GLog ); } Context.World()->bTriggerPostLoadMap = true; } // Tick the viewports. if ( GameViewport != NULL && !bIdleMode ) { SCOPE_CYCLE_COUNTER(STAT_GameViewportTick); GameViewport->Tick(DeltaSeconds); } UpdateTransitionType(Context.World()); // fixme: this will only happen once due to the static bool, but still need to figure out how to handle this for multiple worlds if (FPlatformProperties::SupportsWindowedMode()) { // Hide the splashscreen and show the game window static bool bFirstTime = true; if ( bFirstTime ) { bFirstTime = false; FPlatformSplash::Hide(); if ( GameViewportWindow.IsValid() ) { GameViewportWindow.Pin()->ShowWindow(); FSlateApplication::Get().RegisterGameViewport( GameViewportWidget.ToSharedRef() ); } } } if (!bIdleMode && !IsRunningDedicatedServer() && !IsRunningCommandlet()) { // Render everything. RedrawViewports(); } // Block on async loading if requested. if( Context.World()->bRequestedBlockOnAsyncLoading ) { // Only perform work if there is anything to do. This ensures we are not syncronizing with the GPU // and suspending the device needlessly. bool bWorkToDo = IsAsyncLoading(); if (!bWorkToDo) { Context.World()->UpdateLevelStreaming(); bWorkToDo = Context.World()->IsVisibilityRequestPending(); } if (bWorkToDo) { // tell clients to do the same so they don't fall behind for( FConstPlayerControllerIterator Iterator = Context.World()->GetPlayerControllerIterator(); Iterator; ++Iterator ) { APlayerController* PlayerController = *Iterator; UNetConnection* Conn = Cast<UNetConnection>(PlayerController->Player); if (Conn != NULL && Conn->GetUChildConnection() == NULL) { // call the event to replicate the call PlayerController->ClientSetBlockOnAsyncLoading(); // flush the connection to make sure it gets sent immediately Conn->FlushNet(true); } } FStreamingPause::GameThreadWantsToSuspendRendering( GameViewport ? GameViewport->Viewport : NULL ); // Flushes level streaming requests, blocking till completion. Context.World()->FlushLevelStreaming(); FStreamingPause::GameThreadWantsToResumeRendering(); } Context.World()->bRequestedBlockOnAsyncLoading = false; } // streamingServer if( GIsServer == true ) { SCOPE_CYCLE_COUNTER(STAT_UpdateLevelStreaming); Context.World()->UpdateLevelStreaming(); } // Update Audio. This needs to occur after rendering as the rendering code updates the listener position. if( GetAudioDevice() ) { GetAudioDevice()->Update( !Context.World()->IsPaused() ); } if( GIsClient ) { // GStreamingManager is updated outside of a world context. For now, assuming it needs to tick here, before possibly calling PostLoadMap. // Will need to take another look when trying to support multiple worlds. // Update resource streaming after viewports have had a chance to update view information. Normal update. GStreamingManager->Tick( DeltaSeconds ); if ( Context.World()->bTriggerPostLoadMap ) { Context.World()->bTriggerPostLoadMap = false; // Turns off the loading movie (if it was turned on by LoadMap) and other post-load cleanup. PostLoadMap(); } } UNCLOCK_CYCLES(LocalTickCycles); TickCycles=LocalTickCycles; // See whether any map changes are pending and we requested them to be committed. ConditionalCommitMapChange(Context); } // ---------------------------- // End per-world ticking // ---------------------------- // Restore original GWorld*. This will go away one day. if (OriginalGWorldContext != INDEX_NONE) { GWorld = WorldContextFromHandle(OriginalGWorldContext).World(); } // tell renderer about GWorld->IsPaused(), before rendering { ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER( SetPaused, bool, bGamePaused, WorldWasPaused, { GRenderingRealtimeClock.SetGamePaused(bGamePaused); }); }