157 lines
5.6 KiB
C#
157 lines
5.6 KiB
C#
using Aspire.Hosting.Lifecycle;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace AppHost;
|
|
|
|
// https://github.com/maddymontaquila/Godot-SnakeCS/blob/maddy/aspire/AppHost/GodotExtensions.cs
|
|
public static class GodotExtensions
|
|
{
|
|
/// <summary>
|
|
/// Adds a Godot project to the application model.
|
|
/// </summary>
|
|
/// <param name="builder">The distributed application builder.</param>
|
|
/// <param name="projectPath">The path to the Godot project file (.godot).</param>
|
|
/// <param name="name">The name of the resource.</param>
|
|
/// <param name="args">Optional arguments to pass to the Godot executable.</param>
|
|
/// <returns>A reference to the Godot project resource.</returns>
|
|
public static IResourceBuilder<ExecutableResource> AddGodot(
|
|
this IDistributedApplicationBuilder builder,
|
|
string projectPath,
|
|
string? name = null,
|
|
params string[] args)
|
|
{
|
|
name ??= Path.GetFileNameWithoutExtension(projectPath);
|
|
var projectDirectory = Path.GetDirectoryName(projectPath) ?? ".";
|
|
var godotPath = GetGodotExecutablePath();
|
|
|
|
// Build the arguments list
|
|
var arguments = new List<string>
|
|
{
|
|
"--path",
|
|
projectDirectory,
|
|
//"--verbose"
|
|
};
|
|
|
|
// Add any custom args
|
|
arguments.AddRange(args);
|
|
|
|
// Create a standard ExecutableResource (since custom ones don't seem to work well)
|
|
var godotResource = builder.AddExecutable(
|
|
name: name,
|
|
command: godotPath,
|
|
workingDirectory: projectDirectory,
|
|
args: arguments.ToArray());
|
|
//.WithEnvironment("OTEL_EXPORTER_OTLP_ENDPOINT", Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") ?? throw new InvalidOperationException("OTEL_EXPORTER_OTLP_ENDPOINT environment variable is not set"));
|
|
|
|
// Add a lifecycle hook to handle building before startup
|
|
builder.Services.AddSingleton<IDistributedApplicationLifecycleHook>(sp =>
|
|
new GodotBuildHook(
|
|
projectPath,
|
|
projectDirectory,
|
|
sp.GetRequiredService<ILogger<GodotBuildHook>>()));
|
|
|
|
return godotResource;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Godot executable path based on the current platform.
|
|
/// </summary>
|
|
private static string GetGodotExecutablePath()
|
|
{
|
|
// First check for GODOT environment variable
|
|
var godotPath = Environment.GetEnvironmentVariable("GODOT");
|
|
if (!string.IsNullOrWhiteSpace(godotPath))
|
|
{
|
|
return godotPath;
|
|
}
|
|
|
|
// Fallback to platform-specific defaults
|
|
if (OperatingSystem.IsMacOS())
|
|
{
|
|
return "godot";
|
|
}
|
|
else if (OperatingSystem.IsWindows())
|
|
{
|
|
return "godot.exe";
|
|
}
|
|
else if (OperatingSystem.IsLinux())
|
|
{
|
|
return "godot";
|
|
}
|
|
|
|
throw new PlatformNotSupportedException("Current platform is not supported for Godot execution.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lifecycle hook to build the Godot project before launching
|
|
/// </summary>
|
|
private class GodotBuildHook : IDistributedApplicationLifecycleHook
|
|
{
|
|
private readonly string _projectPath;
|
|
private readonly string _projectDirectory;
|
|
private readonly ILogger<GodotBuildHook> _logger;
|
|
|
|
public GodotBuildHook(string projectPath, string projectDirectory, ILogger<GodotBuildHook> logger)
|
|
{
|
|
_projectPath = projectPath;
|
|
_projectDirectory = projectDirectory;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task BeforeStartAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
|
{
|
|
_logger.LogInformation("Building Godot project: {ProjectPath}", _projectPath);
|
|
|
|
// Execute dotnet build on the project
|
|
var buildProcess = new System.Diagnostics.Process
|
|
{
|
|
StartInfo = new System.Diagnostics.ProcessStartInfo
|
|
{
|
|
FileName = "dotnet",
|
|
Arguments = $"build \"{_projectPath}\" --configuration Debug",
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
WorkingDirectory = _projectDirectory
|
|
}
|
|
};
|
|
|
|
buildProcess.OutputDataReceived += (sender, e) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(e.Data))
|
|
{
|
|
_logger.LogInformation("[Godot Build] {Data}", e.Data);
|
|
}
|
|
};
|
|
|
|
buildProcess.ErrorDataReceived += (sender, e) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(e.Data))
|
|
{
|
|
_logger.LogError("[Godot Build] {Data}", e.Data);
|
|
}
|
|
};
|
|
|
|
buildProcess.Start();
|
|
buildProcess.BeginOutputReadLine();
|
|
buildProcess.BeginErrorReadLine();
|
|
await buildProcess.WaitForExitAsync(cancellationToken);
|
|
|
|
if (buildProcess.ExitCode != 0)
|
|
{
|
|
_logger.LogError("Failed to build Godot project: {ProjectPath}", _projectPath);
|
|
return;
|
|
}
|
|
|
|
_logger.LogInformation("Successfully built Godot project: {ProjectPath}", _projectPath);
|
|
}
|
|
|
|
public Task AfterStartAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
}
|