示例#1
0
bool UDemoNetDriver::InitConnect( FNetworkNotify* InNotify, const FURL& ConnectURL, FString& Error )
{
	if ( GetWorld() == nullptr )
	{
		UE_LOG( LogDemo, Error, TEXT( "GetWorld() == nullptr" ) );
		return false;
	}

	if ( GetWorld()->GetGameInstance() == nullptr )
	{
		UE_LOG( LogDemo, Error, TEXT( "GetWorld()->GetGameInstance() == nullptr" ) );
		return false;
	}

	UGameInstance* GameInstance = GetWorld()->GetGameInstance();

	// handle default initialization
	if ( !InitBase( true, InNotify, ConnectURL, false, Error ) )
	{
		GameInstance->HandleDemoPlaybackFailure( EDemoPlayFailure::Generic, FString( TEXT( "InitBase FAILED" ) ) );
		return false;
	}

	ResetDemoState();

	// open the pre-recorded demo file
	FileAr = IFileManager::Get().CreateFileReader( *DemoFilename );

	if ( !FileAr )
	{
		Error = FString::Printf( TEXT( "Couldn't open demo file %s for reading" ), *DemoFilename );
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error );
		GameInstance->HandleDemoPlaybackFailure( EDemoPlayFailure::DemoNotFound, FString( EDemoPlayFailure::ToString( EDemoPlayFailure::DemoNotFound ) ) );
		return false;
	}

	// Playback, local machine is a client, and the demo stream acts "as if" it's the server.
	ServerConnection = ConstructObject<UNetConnection>( UDemoNetConnection::StaticClass() );
	ServerConnection->InitConnection( this, USOCK_Pending, ConnectURL, 1000000 );

	// use the same byte format regardless of platform so that the demos are cross platform
	// DEMO_FIXME: This is messing up for some reason, investigate
	//FileAr->SetByteSwapping( true );

	FNetworkDemoHeader DemoHeader;

	(*FileAr) << DemoHeader;

	// Check magic value
	if ( DemoHeader.Magic != NETWORK_DEMO_MAGIC )
	{
		Error = FString( TEXT( "Demo file is corrupt" ) );
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error );
		GameInstance->HandleDemoPlaybackFailure( EDemoPlayFailure::Corrupt, Error );
		return false;
	}

	// Check version
	if ( DemoHeader.Version != NETWORK_DEMO_VERSION )
	{
		Error = FString( TEXT( "Demo file version is incorrect" ) );
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error );
		GameInstance->HandleDemoPlaybackFailure( EDemoPlayFailure::InvalidVersion, Error );
		return false;
	}

	// Create fake control channel
	ServerConnection->CreateChannel( CHTYPE_Control, 1 );

	DemoTotalFrames = DemoHeader.NumFrames;
	DemoTotalTime	= DemoHeader.TotalTime;

	UE_LOG( LogDemo, Log, TEXT( "Starting demo playback with demo. Filename: %s, Frames: %i, Version %i" ), *DemoFilename, DemoTotalFrames, DemoHeader.Version );

	// Bypass UDemoPendingNetLevel
	FString LoadMapError;

	FURL DemoURL;
	DemoURL.Map = DemoHeader.LevelName;

	FWorldContext * WorldContext = GEngine->GetWorldContextFromWorld( GetWorld() );

	if ( WorldContext == NULL )
	{
		Error = FString::Printf( TEXT( "No world context" ), *DemoFilename );
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error );
		GameInstance->HandleDemoPlaybackFailure( EDemoPlayFailure::Generic, FString( TEXT( "No world context" ) ) );
		return false;
	}

	GetWorld()->DemoNetDriver = NULL;
	SetWorld( NULL );

	auto NewPendingNetGame = NewObject<UDemoPendingNetGame>();

	NewPendingNetGame->DemoNetDriver = this;

	WorldContext->PendingNetGame = NewPendingNetGame;

	if ( !GEngine->LoadMap( *WorldContext, DemoURL, NewPendingNetGame, LoadMapError ) )
	{
		Error = LoadMapError;
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: LoadMap failed: failed: %s" ), *Error );
		GameInstance->HandleDemoPlaybackFailure( EDemoPlayFailure::Generic, FString( TEXT( "LoadMap failed" ) ) );
		return false;
	}

	SetWorld( WorldContext->World() );
	WorldContext->World()->DemoNetDriver = this;
	WorldContext->PendingNetGame = NULL;

	// Remember where we are
	const int32 OldPos = FileAr->Tell();

	// Jump to meta data
	FileAr->Seek( DemoHeader.MetaDataOffset );

	// Read meta data
	for ( int32 i = 0; i < DemoHeader.NumStreamingLevels; ++i )
	{
		ULevelStreamingKismet* StreamingLevel = static_cast<ULevelStreamingKismet*>(StaticConstructObject(ULevelStreamingKismet::StaticClass(), GetWorld(), NAME_None, RF_NoFlags, NULL ) );

		StreamingLevel->bShouldBeLoaded		= true;
		StreamingLevel->bShouldBeVisible	= true;
		StreamingLevel->bShouldBlockOnLoad	= false;
		StreamingLevel->bInitiallyLoaded	= true;
		StreamingLevel->bInitiallyVisible	= true;

		FString PackageName;
		FString PackageNameToLoad;

		(*FileAr) << PackageName;
		(*FileAr) << PackageNameToLoad;
		(*FileAr) << StreamingLevel->LevelTransform;

		StreamingLevel->PackageNameToLoad = FName( *PackageNameToLoad );
		StreamingLevel->SetWorldAssetByPackageName( FName( *PackageName ) );

		GetWorld()->StreamingLevels.Add( StreamingLevel );

		UE_LOG( LogDemo, Log, TEXT( "  Loading streamingLevel: %s, %s" ), *PackageName, *PackageNameToLoad );
	}

	// Jump back to start of stream
	FileAr->Seek( OldPos );

	// Remember where the meta data is, this is where we must stop reading the demo stream
	EndOfStreamOffset = DemoHeader.MetaDataOffset;

	return true;
}
示例#2
0
bool UDemoNetDriver::InitConnect( FNetworkNotify* InNotify, const FURL& ConnectURL, FString& Error )
{
	// handle default initialization
	if ( !InitBase( true, InNotify, ConnectURL, false, Error ) )
	{
		return false;
	}

	// open the pre-recorded demo file
	FileAr = IFileManager::Get().CreateFileReader( *DemoFilename );

	if ( !FileAr )
	{
		Error = FString::Printf( TEXT( "Couldn't open demo file %s for reading" ), *DemoFilename );
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error );
		return false;
	}

	// Playback, local machine is a client, and the demo stream acts "as if" it's the server.
	ServerConnection = ConstructObject<UNetConnection>( UDemoNetConnection::StaticClass() );
	ServerConnection->InitConnection( this, USOCK_Pending, ConnectURL, 1000000 );

#if 1
	// Create fake control channel
	ServerConnection->CreateChannel( CHTYPE_Control, 1 );
#endif

	// use the same byte format regardless of platform so that the demos are cross platform
	// DEMO_FIXME: This is messing up for some reason, investigate
	//FileAr->SetByteSwapping( true );

	int32 EngineVersion = 0;
	(*FileAr) << EngineVersion;
	(*FileAr) << PlaybackTotalFrames;

	UE_LOG( LogDemo, Log, TEXT( "Starting demo playback with demo. Filename: %s, Frames: %i, Version %i" ), *DemoFilename, PlaybackTotalFrames, EngineVersion );

#if 1
	// Bypass UDemoPendingNetLevel
	FString LevelName;
	(*FileAr) << LevelName;

	FString LoadMapError;

	FURL DemoURL;
	DemoURL.Map = LevelName;

	FWorldContext * WorldContext = GEngine->GetWorldContextFromWorld( World );

	if ( WorldContext == NULL )
	{
		Error = FString::Printf( TEXT( "No world context" ), *DemoFilename );
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error );
		return false;
	}

	World->DemoNetDriver = NULL;
	SetWorld( NULL );

	UDemoPendingNetGame * NewPendingNetGame = new UDemoPendingNetGame( FPostConstructInitializeProperties() );

	NewPendingNetGame->DemoNetDriver = this;

	WorldContext->PendingNetGame = NewPendingNetGame;

	if ( !GEngine->LoadMap( *WorldContext, DemoURL, NewPendingNetGame, LoadMapError ) )
	{
		Error = LoadMapError;
		UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: LoadMap failed: failed: %s" ), *Error );
		return false;
	}

	SetWorld( WorldContext->World() );
	WorldContext->World()->DemoNetDriver = this;
	WorldContext->PendingNetGame = NULL;
#endif

	int32 NumStreamingLevels = 0;

	(*FileAr) << NumStreamingLevels;

	for ( int32 i = 0; i < NumStreamingLevels; ++i )
	{
		ULevelStreamingKismet* StreamingLevel = static_cast<ULevelStreamingKismet*>(StaticConstructObject(ULevelStreamingKismet::StaticClass(), GetWorld(), NAME_None, RF_NoFlags, NULL ) );

		StreamingLevel->bShouldBeLoaded		= true;
		StreamingLevel->bShouldBeVisible	= true;
		StreamingLevel->bShouldBlockOnLoad	= false;
		StreamingLevel->bInitiallyLoaded	= true;
		StreamingLevel->bInitiallyVisible	= true;

		FString PackageName;
		FString PackageNameToLoad;

		(*FileAr) << PackageName;
		(*FileAr) << PackageNameToLoad;
		(*FileAr) << StreamingLevel->LevelTransform;

		StreamingLevel->PackageNameToLoad = FName( *PackageNameToLoad );
		StreamingLevel->SetWorldAssetByPackageName( FName( *PackageName ) );

		GetWorld()->StreamingLevels.Add( StreamingLevel );

		UE_LOG( LogDemo, Log, TEXT( "  Loading streamingLevel: %s, %s" ), *PackageName, *PackageNameToLoad );
	}

	DemoDeltaTime = 0;

	return true;
}