Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Bugfix - Fix up Fast Local Restart issues #1139

Merged
merged 10 commits into from
Jul 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [`0.6.0`] - 2019-07-09

### Features:
- Automatic local deployment starting. Local deployments are now started automatically for you when pressing the 'Play' button. Local deployment start time has been reduced to around 5.5s~. If your schema has changed during a deployment, the next time you press play the local deployment will be automatically restarted. There is no longer a `spatial` cmd window for a local deployment, the Unreal output window will still contain logs. Runtime logs can be found at `spatial\logs\localdeployment\%timestamp%\runtime.log`. A new option `Show spatial service button` in the SpatialOS Settings menu allows you to turn the 'spatial service' on and off via the SpatialGDK Toolbar for debugging purposes.
- Automatic local deployment starting. Local deployments are now started automatically for you when pressing the 'Play' button. Local deployment start time has been reduced to around 5.5s~. If your schema has changed during a deployment, the next time you press play the local deployment will be automatically restarted. There is no longer a `spatial` cmd window for a local deployment, the Unreal output window will still contain logs. Runtime logs can be found at `spatial\logs\localdeployment\%timestamp%\runtime.log`. A new option `Show spatial service button` in the SpatialOS Settings menu allows you to turn the 'spatial service' on and off via the SpatialGDK Toolbar for debugging purposes. Each time you start the editor in any project the 'spatial service' will be restarted, this is to ensure the service is always running in the correct SpatialOS project.
- Added external schema code-generation tool for [non-Unreal server-worker types]({{urlRoot}}/content/non-unreal-server-worker-types). If you create non-Unreal server-worker types using the [SpatialOS Worker SDK](https://docs.improbable.io/reference/13.8/shared/sdks-and-data-overview) outside of the GDK and your Unreal Engine, you manually create [schema]({{urlRoot}/content/glossary#schema). Use the new [helper-script]({{urlRoot}}/content/helper-scripts) to generate Unreal code from manually-created schema; it enables your Unreal game code to interoperate with non-Unreal server-worker types.
- Added simulated player tools, which will allow you to create logic to simulate the behavior of real players. Simulated players can be used to scale test your game to hundreds of players. Simulated players can be launched locally as part of your development flow for quick iteration, as well as part of a separate "simulated player deployment" to connect a configurable amount of simulated players to your running game deployment.
- Factored out writing of Linux worker start scripts into a library, and added a standalone `WriteLinuxScript.exe` to _just_ write the launch script (for use in custom build pipelines).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,14 @@ TSharedRef<SWidget> FSpatialGDKEditorToolbarModule::CreateGenerateSchemaMenuCont

void FSpatialGDKEditorToolbarModule::CreateSnapshotButtonClicked()
{
ShowTaskStartNotification("Started snapshot generation");
OnShowTaskStartNotification("Started snapshot generation");

const USpatialGDKEditorSettings* Settings = GetDefault<USpatialGDKEditorSettings>();

SpatialGDKEditorInstance->GenerateSnapshot(
GEditor->GetEditorWorldContext().World(), Settings->GetSpatialOSSnapshotFile(),
FSimpleDelegate::CreateLambda([this]() { ShowSuccessNotification("Snapshot successfully generated!"); }),
FSimpleDelegate::CreateLambda([this]() { ShowFailedNotification("Snapshot generation failed!"); }),
FSimpleDelegate::CreateLambda([this]() { OnShowSuccessNotification("Snapshot successfully generated!"); }),
FSimpleDelegate::CreateLambda([this]() { OnShowFailedNotification("Snapshot generation failed!"); }),
FSpatialGDKEditorErrorHandler::CreateLambda([](FString ErrorText) { FMessageDialog::Debugf(FText::FromString(ErrorText)); }));
}

Expand All @@ -292,40 +292,62 @@ void FSpatialGDKEditorToolbarModule::SchemaGenerateFullButtonClicked()
GenerateSchema(true);
}

void FSpatialGDKEditorToolbarModule::ShowTaskStartNotification(const FString& NotificationText)
void FSpatialGDKEditorToolbarModule::OnShowTaskStartNotification(const FString& NotificationText)
{
AsyncTask(ENamedThreads::GameThread, [this, NotificationText] {
if (TaskNotificationPtr.IsValid())
AsyncTask(ENamedThreads::GameThread, [NotificationText]
{
if (FSpatialGDKEditorToolbarModule* Module = FModuleManager::GetModulePtr<FSpatialGDKEditorToolbarModule>("SpatialGDKEditorToolbar"))
{
TaskNotificationPtr.Pin()->ExpireAndFadeout();
Module->ShowTaskStartNotification(NotificationText);
}
});
}

if (GEditor && ExecutionStartSound)
{
GEditor->PlayEditorSound(ExecutionStartSound);
}
void FSpatialGDKEditorToolbarModule::ShowTaskStartNotification(const FString& NotificationText)
{
// If a task notification already exists then expire it.
if (TaskNotificationPtr.IsValid())
{
TaskNotificationPtr.Pin()->ExpireAndFadeout();
}

FNotificationInfo Info(FText::AsCultureInvariant(NotificationText));
Info.Image = FSpatialGDKEditorToolbarStyle::Get().GetBrush(TEXT("SpatialGDKEditorToolbar.SpatialOSLogo"));
Info.ExpireDuration = 5.0f;
Info.bFireAndForget = false;
if (GEditor && ExecutionStartSound)
{
GEditor->PlayEditorSound(ExecutionStartSound);
}

TaskNotificationPtr = FSlateNotificationManager::Get().AddNotification(Info);
FNotificationInfo Info(FText::AsCultureInvariant(NotificationText));
Info.Image = FSpatialGDKEditorToolbarStyle::Get().GetBrush(TEXT("SpatialGDKEditorToolbar.SpatialOSLogo"));
Info.ExpireDuration = 5.0f;
Info.bFireAndForget = false;

if (TaskNotificationPtr.IsValid())
TaskNotificationPtr = FSlateNotificationManager::Get().AddNotification(Info);

if (TaskNotificationPtr.IsValid())
{
TaskNotificationPtr.Pin()->SetCompletionState(SNotificationItem::CS_Pending);
}
}

void FSpatialGDKEditorToolbarModule::OnShowSuccessNotification(const FString& NotificationText)
{
AsyncTask(ENamedThreads::GameThread, [NotificationText]
{
if (FSpatialGDKEditorToolbarModule* Module = FModuleManager::GetModulePtr<FSpatialGDKEditorToolbarModule>("SpatialGDKEditorToolbar"))
{
TaskNotificationPtr.Pin()->SetCompletionState(SNotificationItem::CS_Pending);
Module->ShowSuccessNotification(NotificationText);
}
});
}

void FSpatialGDKEditorToolbarModule::ShowSuccessNotification(const FString& NotificationText)
{
AsyncTask(ENamedThreads::GameThread, [this, NotificationText]{
TSharedPtr<SNotificationItem> Notification = TaskNotificationPtr.Pin();
TSharedPtr<SNotificationItem> Notification = TaskNotificationPtr.Pin();
if (Notification.IsValid())
{
Notification->SetFadeInDuration(0.1f);
Notification->SetFadeOutDuration(0.5f);
Notification->SetExpireDuration(7.5f);
Notification->SetExpireDuration(5.0f);
Notification->SetText(FText::AsCultureInvariant(NotificationText));
Notification->SetCompletionState(SNotificationItem::CS_Success);
Notification->ExpireAndFadeout();
Expand All @@ -334,24 +356,37 @@ void FSpatialGDKEditorToolbarModule::ShowSuccessNotification(const FString& Noti
{
GEditor->PlayEditorSound(ExecutionSuccessSound);
}
}
}

void FSpatialGDKEditorToolbarModule::OnShowFailedNotification(const FString& NotificationText)
{
AsyncTask(ENamedThreads::GameThread, [NotificationText]
{
if (FSpatialGDKEditorToolbarModule* Module = FModuleManager::GetModulePtr<FSpatialGDKEditorToolbarModule>("SpatialGDKEditorToolbar"))
{
Module->ShowFailedNotification(NotificationText);
}
});
}

void FSpatialGDKEditorToolbarModule::ShowFailedNotification(const FString& NotificationText)
{
AsyncTask(ENamedThreads::GameThread, [this, NotificationText]{
TSharedPtr<SNotificationItem> Notification = TaskNotificationPtr.Pin();
TSharedPtr<SNotificationItem> Notification = TaskNotificationPtr.Pin();
if (Notification.IsValid())
{
Notification->SetFadeInDuration(0.1f);
Notification->SetFadeOutDuration(0.5f);
Notification->SetExpireDuration(5.0);
Notification->SetText(FText::AsCultureInvariant(NotificationText));
Notification->SetCompletionState(SNotificationItem::CS_Fail);
Notification->SetExpireDuration(5.0f);

Notification->ExpireAndFadeout();

if (GEditor && ExecutionFailSound)
{
GEditor->PlayEditorSound(ExecutionFailSound);
}
});
}
}

bool FSpatialGDKEditorToolbarModule::ValidateGeneratedLaunchConfig() const
Expand Down Expand Up @@ -448,18 +483,18 @@ void FSpatialGDKEditorToolbarModule::StartSpatialServiceButtonClicked()
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this]
{
FDateTime StartTime = FDateTime::Now();
ShowTaskStartNotification(TEXT("Starting spatial service..."));
OnShowTaskStartNotification(TEXT("Starting spatial service..."));

if (!LocalDeploymentManager->TryStartSpatialService())
{
ShowFailedNotification(TEXT("Spatial service failed to start"));
OnShowFailedNotification(TEXT("Spatial service failed to start"));
UE_LOG(LogSpatialGDKEditorToolbar, Error, TEXT("Could not start spatial service."));
return;
}

FTimespan Span = FDateTime::Now() - StartTime;

ShowSuccessNotification(TEXT("Spatial service started!"));
OnShowSuccessNotification(TEXT("Spatial service started!"));
UE_LOG(LogSpatialGDKEditorToolbar, Log, TEXT("Spatial service started in %f seconds."), Span.GetTotalSeconds());
});
}
Expand All @@ -469,18 +504,18 @@ void FSpatialGDKEditorToolbarModule::StopSpatialServiceButtonClicked()
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this]
{
FDateTime StartTime = FDateTime::Now();
ShowTaskStartNotification(TEXT("Stopping spatial service..."));
OnShowTaskStartNotification(TEXT("Stopping spatial service..."));

if (!LocalDeploymentManager->TryStopSpatialService())
{
ShowFailedNotification(TEXT("Spatial service failed to stop"));
OnShowFailedNotification(TEXT("Spatial service failed to stop"));
UE_LOG(LogSpatialGDKEditorToolbar, Error, TEXT("Could not stop spatial service."));
return;
}

FTimespan Span = FDateTime::Now() - StartTime;

ShowSuccessNotification(TEXT("Spatial service stopped!"));
OnShowSuccessNotification(TEXT("Spatial service stopped!"));
UE_LOG(LogSpatialGDKEditorToolbar, Log, TEXT("Spatial service stopped in %f secoonds."), Span.GetTotalSeconds());
});
}
Expand Down Expand Up @@ -529,10 +564,10 @@ void FSpatialGDKEditorToolbarModule::VerifyAndStartDeployment()
}

// If schema has been regenerated then we need to restart spatial.
if (bRedeployRequired)
if (bRedeployRequired && LocalDeploymentManager->IsLocalDeploymentRunning())
{
UE_LOG(LogSpatialGDKEditorToolbar, Display, TEXT("Schema has changed since last session. Local deployment must restart."));
ShowTaskStartNotification(TEXT("Schema has changed. Local deployment restarting."));
OnShowTaskStartNotification(TEXT("Schema has changed. Local deployment restarting."));
LocalDeploymentManager->TryStopLocalDeployment();
bRedeployRequired = false;
}
Expand All @@ -542,14 +577,14 @@ void FSpatialGDKEditorToolbarModule::VerifyAndStartDeployment()
return;
}

ShowTaskStartNotification(TEXT("Starting local deployment..."));
OnShowTaskStartNotification(TEXT("Starting local deployment..."));
if (LocalDeploymentManager->TryStartLocalDeployment(LaunchConfig, LaunchFlags))
{
ShowSuccessNotification(TEXT("Local deployment started!"));
OnShowSuccessNotification(TEXT("Local deployment started!"));
}
else
{
ShowFailedNotification(TEXT("Local deployment failed to start"));
OnShowFailedNotification(TEXT("Local deployment failed to start"));
}
});
}
Expand All @@ -563,14 +598,14 @@ void FSpatialGDKEditorToolbarModule::StopSpatialDeploymentButtonClicked()
{
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this]
{
ShowTaskStartNotification(TEXT("Stopping local deployment..."));
OnShowTaskStartNotification(TEXT("Stopping local deployment..."));
if (LocalDeploymentManager->TryStopLocalDeployment())
{
ShowSuccessNotification(TEXT("Successfully stopped local deployment"));
OnShowSuccessNotification(TEXT("Successfully stopped local deployment"));
}
else
{
ShowFailedNotification(TEXT("Failed to stop local deployment!"));
OnShowFailedNotification(TEXT("Failed to stop local deployment!"));
}
});
}
Expand Down Expand Up @@ -808,41 +843,41 @@ void FSpatialGDKEditorToolbarModule::GenerateSchema(bool bFullScan)

if (SpatialGDKEditorInstance->FullScanRequired())
{
ShowTaskStartNotification("Initial Schema Generation");
OnShowTaskStartNotification("Initial Schema Generation");

if (SpatialGDKEditorInstance->GenerateSchema(true))
{
ShowSuccessNotification("Initial Schema Generation completed!");
OnShowSuccessNotification("Initial Schema Generation completed!");
}
else
{
ShowFailedNotification("Initial Schema Generation failed");
OnShowFailedNotification("Initial Schema Generation failed");
}
}
else if (bFullScan)
{
ShowTaskStartNotification("Generating Schema (Full)");
OnShowTaskStartNotification("Generating Schema (Full)");

if (SpatialGDKEditorInstance->GenerateSchema(true))
{
ShowSuccessNotification("Full Schema Generation completed!");
OnShowSuccessNotification("Full Schema Generation completed!");
}
else
{
ShowFailedNotification("Full Schema Generation failed");
OnShowFailedNotification("Full Schema Generation failed");
}
}
else
{
ShowTaskStartNotification("Generating Schema (Incremental)");
OnShowTaskStartNotification("Generating Schema (Incremental)");

if (SpatialGDKEditorInstance->GenerateSchema(false))
{
ShowSuccessNotification("Incremental Schema Generation completed!");
OnShowSuccessNotification("Incremental Schema Generation completed!");
}
else
{
ShowFailedNotification("Incremental Schema Generation failed");
OnShowFailedNotification("Incremental Schema Generation failed");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,13 @@ class FSpatialGDKEditorToolbarModule : public IModuleInterface, public FTickable

TSharedRef<SWidget> CreateGenerateSchemaMenuContent();

void OnShowTaskStartNotification(const FString& NotificationText);
void ShowTaskStartNotification(const FString& NotificationText);

void OnShowSuccessNotification(const FString& NotificationText);
void ShowSuccessNotification(const FString& NotificationText);

void OnShowFailedNotification(const FString& NotificationText);
void ShowFailedNotification(const FString& NotificationText);

bool ValidateGeneratedLaunchConfig() const;
Expand Down
Loading