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

Commit

Permalink
Bugfix - Fix up Fast Local Restart issues (#1139)
Browse files Browse the repository at this point in the history
* Fixed potential bad states and check for GEditor

* Made notificaitons safe

* Remove uneeded IsValid

* Grab module dynamically

* Remove pragma

* Made GetProjectName safer and restart spatial service on every project start

* Updated changelog

* Better logging for 'not available' project file

* Removed preventing start local deployment if the we suspect the spatial service is in the wrong project

* Always try to stop the service
  • Loading branch information
joshuahuburn authored Jul 10, 2019
1 parent 59632c4 commit f66f470
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 84 deletions.
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

0 comments on commit f66f470

Please sign in to comment.