private static string[] ConstructArgs(string projectPath, string schemaCompilerPath, string workerJsonPath) { var baseArgs = new List <string> { "run", "-p", $"\"{projectPath}\"", "--", $"--json-dir=\"{ImprobableJsonDir}\"", $"--schema-compiler-path=\"{schemaCompilerPath}\"", $"--worker-json-dir=\"{workerJsonPath}\"" }; var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); baseArgs.Add($"--native-output-dir=\"{toolsConfig.CodegenOutputDir}\""); // Add user defined schema directories baseArgs.AddRange(toolsConfig.SchemaSourceDirs .Where(Directory.Exists) .Select(directory => $"--schema-path=\"{directory}\"")); // Add package schema directories baseArgs.AddRange(GetSchemaDirectories() .Select(directory => $"--schema-path=\"{directory}\"")); // Schema Descriptor baseArgs.Add($"--descriptor-dir=\"{toolsConfig.DescriptorOutputDir}\""); baseArgs.AddRange( toolsConfig.SerializationOverrides.Select(@override => $"--serialization-override=\"{@override}\"")); return(baseArgs.ToArray()); }
private static void CopySchema() { try { var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); // Safe as we validate there is at least one entry. var schemaRoot = toolsConfig.SchemaSourceDirs[0]; CleanDestination(schemaRoot); var packages = Common.GetManifestDependencies().Where(kv => kv.Value.StartsWith("file:")) .ToDictionary(kv => kv.Key, RemoveFilePrefix) .ToDictionary(kv => kv.Key, kv => Path.Combine("Packages", kv.Value)); var schemaSources = packages.Where(SchemaPathExists) .ToDictionary(kv => kv.Key, GetSchemaPath); foreach (var source in schemaSources) { CopySchemaFiles(schemaRoot, source); } } catch (Exception e) { Console.Error.WriteLine(e.Message); Environment.Exit(1); } }
private static void CopySchema() { try { var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); // Safe as we validate there is at least one entry. var schemaRoot = toolsConfig.SchemaSourceDirs[0]; CleanDestination(schemaRoot); // Get all packages we depend on var request = Client.List(offlineMode: true); while (!request.IsCompleted) { // Wait for the request to complete } var schemaSources = request.Result.ToDictionary(package => package.name, package => Path.Combine(package.resolvedPath, "Schema")) .Where(kv => Directory.Exists(kv.Value)); foreach (var source in schemaSources) { CopySchemaFiles(schemaRoot, source.Key, source.Value); } } catch (Exception e) { Console.Error.WriteLine(e.Message); Environment.Exit(1); } }
private static string[] ConstructArgs(string projectPath, string schemaCompilerPath, string workerJsonPath) { var baseArgs = new List <string> { "run", "-p", $"\"{projectPath}\"", "--", $"--json-dir=\"{ImprobableJsonDir}\"", $"--schema-compiler-path=\"{schemaCompilerPath}\"", $"--worker-json-dir=\"{workerJsonPath}\"" }; var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); baseArgs.Add($"--native-output-dir=\"{toolsConfig.CodegenOutputDir}\""); baseArgs.Add($"--schema-path=\"{toolsConfig.SchemaStdLibDir}\""); foreach (var schemaSourceDir in toolsConfig.SchemaSourceDirs) { baseArgs.Add($"--schema-path=\"{schemaSourceDir}\""); } return(baseArgs.ToArray()); }
private static GdkToolsConfiguration CreateInstance() { var config = new GdkToolsConfiguration(); File.WriteAllText(JsonFilePath, JsonUtility.ToJson(config, true)); return(config); }
private static void ForceGenerate() { var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); if (Directory.Exists(toolsConfig.CodegenOutputDir)) { Directory.Delete(toolsConfig.CodegenOutputDir, true); } Generate(); }
public override void OnActivate(string searchContext, VisualElement rootElement) { if (toolsConfig != null) { return; } toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); Undo.undoRedoPerformed += () => { configErrors = toolsConfig.Validate(); }; }
private static void Generate() { var devAuthToken = string.Empty; var gdkToolsConfiguration = GdkToolsConfiguration.GetOrCreateInstance(); var devAuthTokenFullDir = gdkToolsConfiguration.DevAuthTokenFullDir; var devAuthTokenFilePath = gdkToolsConfiguration.DevAuthTokenFilepath; var devAuthTokenLifetimeHours = $"{gdkToolsConfiguration.DevAuthTokenLifetimeHours}h"; var receivedMessage = string.Empty; RedirectedProcess .Command(Common.SpatialBinary) .WithArgs("project", "auth", "dev-auth-token", "create", "--description", "\"Dev Auth Token\"", "--lifetime", devAuthTokenLifetimeHours, "--json_output") .InDirectory(Common.SpatialProjectRootDir) .AddOutputProcessing(message => receivedMessage = message) .RedirectOutputOptions(OutputRedirectBehaviour.None) .Run(); try { if (Json.Deserialize(receivedMessage).TryGetValue(JsonDataKey, out var jsonData) && ((Dictionary <string, object>)jsonData).TryGetValue(TokenSecretKey, out var tokenSecret)) { devAuthToken = (string)tokenSecret; } } catch (Exception e) { Debug.LogError($"Unable to generate Dev Auth Token. {e.Message}"); return; } if (!Directory.Exists(devAuthTokenFullDir)) { Directory.CreateDirectory(devAuthTokenFullDir); } try { File.WriteAllText(devAuthTokenFilePath, devAuthToken); } catch (Exception e) { Debug.LogError($"Unable to save Dev Auth Token asset. {e.Message}"); return; } Debug.Log($"Saving token {devAuthToken} to {devAuthTokenFilePath}."); AssetDatabase.ImportAsset( Path.Combine("Assets", gdkToolsConfiguration.DevAuthTokenDir, "DevAuthToken.txt"), ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(); }
private void OnEnable() { if (toolsConfig != null) { return; } titleContent = new GUIContent("GDK Tools"); toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); Undo.undoRedoPerformed += () => { configErrors = toolsConfig.Validate(); }; }
public static bool TryGenerate() { var devAuthToken = string.Empty; var gdkToolsConfiguration = GdkToolsConfiguration.GetOrCreateInstance(); var devAuthTokenLifetimeHours = $"{gdkToolsConfiguration.DevAuthTokenLifetimeHours}h"; var receivedMessage = string.Empty; RedirectedProcess .Spatial("project", "auth", "dev-auth-token", "create") .WithArgs("--description", "\"Dev Auth Token\"", "--lifetime", devAuthTokenLifetimeHours, "--json_output") .InDirectory(Common.SpatialProjectRootDir) .AddOutputProcessing(message => receivedMessage = message) .RedirectOutputOptions(OutputRedirectBehaviour.None) .Run(); try { var deserializedMessage = Json.Deserialize(receivedMessage); if (deserializedMessage.TryGetValue(JsonDataKey, out var jsonData) && ((Dictionary <string, object>)jsonData).TryGetValue(JsonTokenSecretKey, out var tokenSecret)) { devAuthToken = (string)tokenSecret; } else { if (deserializedMessage.TryGetValue(JsonErrorKey, out var errorMessage)) { throw new Exception(errorMessage.ToString()); } throw new Exception(string.Empty); } } catch (Exception e) { Debug.LogError($"Unable to generate Dev Auth Token. {e.Message}"); return(false); } Debug.Log($"Saving token to Player Preferences."); PlayerPrefs.SetString(PlayerPrefDevAuthTokenKey, devAuthToken); if (gdkToolsConfiguration.SaveDevAuthTokenToFile) { return(SaveTokenToFile()); } return(true); }
private static void LaunchMenu() { GdkToolsConfiguration toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); if (!File.Exists(toolsConfig.CustomSnapshotPath)) { Debug.LogError($"Snapshot {toolsConfig.CustomSnapshotPath} not found. Make sure the file exists and it has not been moved or renamed"); return; } Debug.Log($"Launching SpatialOS locally with snapshot {toolsConfig.CustomSnapshotPath}."); EditorApplication.delayCall += LaunchLocalDeployment; }
private void OnEnable() { if (toolsConfig != null) { return; } toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); errorLayoutOption.normal.textColor = Color.red; Undo.undoRedoPerformed += () => { configErrors = toolsConfig.Validate(); }; }
private static void ForceGenerate() { File.Delete(StartupCodegenMarkerFile); var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); if (Directory.Exists(toolsConfig.CodegenOutputDir)) { Directory.Delete(toolsConfig.CodegenOutputDir, recursive: true); } SetupProject(); Generate(); }
public static RedirectedProcess Spatial(params string[] args) { var config = GdkToolsConfiguration.GetOrCreateInstance(); if (!string.IsNullOrEmpty(config.EnvironmentPlatform)) { args = args .Append($"--environment={config.EnvironmentPlatform}") .ToArray(); } return(Command(Tools.Common.SpatialBinary) .WithArgs(args)); }
private static string[] ConstructArguments() { var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); var baseArgs = new List <string> { "run", "-p", $"\"{ProjectPath}\"", "--", $"\"{Common.SpatialBinary}\"", $"\"{Common.CoreSdkVersion}\"", $"\"{toolsConfig.SchemaStdLibDir}\"" }; return(baseArgs.ToArray()); }
private static void CopySchema() { try { var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); // Safe as we validate there is at least one entry. var schemaRoot = toolsConfig.SchemaSourceDirs[0]; CleanDestination(schemaRoot); var packages = new Dictionary <string, string>(); var dependencyQueue = new Queue <string>(); // Find and include paths of all direct and nested dependencies. dependencyQueue.Enqueue(Common.ManifestPath); while (dependencyQueue.Count > 0) { var dependencies = GetLocalPathsInPackage(Common.ParseDependencies(dependencyQueue.Dequeue())); foreach (var dependency in dependencies) { if (!packages.ContainsKey(dependency.Key)) { packages.Add(dependency.Key, dependency.Value); dependencyQueue.Enqueue($"{dependency.Value}/package.json"); } } } var schemaSources = packages.Where(SchemaPathExists) .ToDictionary(kv => kv.Key, GetSchemaPath); foreach (var source in schemaSources) { CopySchemaFiles(schemaRoot, source); } } catch (Exception e) { Console.Error.WriteLine(e.Message); Environment.Exit(1); } }
private static bool SaveTokenToFile() { var gdkToolsConfiguration = GdkToolsConfiguration.GetOrCreateInstance(); var devAuthTokenFullDir = gdkToolsConfiguration.DevAuthTokenFullDir; var devAuthTokenFilePath = gdkToolsConfiguration.DevAuthTokenFilepath; if (!PlayerPrefs.HasKey(PlayerPrefDevAuthTokenKey)) { // Given we call SaveTokenToFile after successfully generating a Dev Auth Token, // we should never see the following error. Debug.LogError("Cannot save Development Authentication Token, as it has not been generated."); return(false); } var devAuthToken = PlayerPrefs.GetString(PlayerPrefDevAuthTokenKey); if (!Directory.Exists(devAuthTokenFullDir)) { Directory.CreateDirectory(devAuthTokenFullDir); } try { File.WriteAllText(devAuthTokenFilePath, devAuthToken); } catch (Exception e) { Debug.LogError($"Unable to save Dev Auth Token asset. {e.Message}"); return(false); } Debug.Log($"Saving token to {devAuthTokenFilePath}."); AssetDatabase.ImportAsset(DevAuthTokenAssetPath, ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(); return(true); }
private static void Generate() { try { if (!Common.CheckDependencies()) { return; } if (!File.Exists(CodegenExe)) { SetupProject(); } EditorApplication.LockReloadAssemblies(); Profiler.BeginSample("Add modules"); UpdateModules(); Profiler.EndSample(); Profiler.BeginSample("Code generation"); using (new ShowProgressBarScope("Generating code...")) { ResetCodegenLogCounter(); var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); var loggerOutputPath = toolsConfig.DefaultCodegenLogPath; var exitCode = RedirectedProcess.Command(Common.DotNetBinary) .WithArgs("run", "-p", $"\"{CodegenExe}\"") .RedirectOutputOptions(OutputRedirectBehaviour.None) .AddOutputProcessing(ProcessDotnetOutput) .AddOutputProcessing(ProcessCodegenOutput) .Run(); var numWarnings = codegenLogCounts[CodegenLogLevel.Warn]; var numErrors = codegenLogCounts[CodegenLogLevel.Error] + codegenLogCounts[CodegenLogLevel.Fatal]; if (exitCode.ExitCode != 0 || numErrors > 0) { if (!Application.isBatchMode) { Debug.LogError("Code generation failed! Please check the console for more information."); EditorApplication.delayCall += () => { if (File.Exists(loggerOutputPath)) { var option = EditorUtility.DisplayDialogComplex("Generate Code", $"Code generation failed with {numWarnings} warnings and {numErrors} errors!{Environment.NewLine}{Environment.NewLine}" + $"Please check the code generation logs for more information: {loggerOutputPath}", "Open logfile", "Close", ""); switch (option) { // Open logfile case 0: Application.OpenURL(loggerOutputPath); break; // Close case 1: // Alt case 2: break; default: throw new ArgumentOutOfRangeException(nameof(option), "Unrecognised option"); } } else { DisplayGeneralFailure(); } }; } } else { if (numWarnings > 0) { Debug.LogWarning($"Code generation completed successfully with {numWarnings} warnings. Please check the logs for more information: {loggerOutputPath}"); } else { Debug.Log("Code generation complete!"); } File.WriteAllText(StartupCodegenMarkerFile, string.Empty); } } AssetDatabase.Refresh(); } catch (Exception e) { Debug.LogException(e); } finally { Profiler.EndSample(); EditorApplication.UnlockReloadAssemblies(); } }
internal static void GenerateCodegenRunConfigs() { var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); // Ensure tools config is valid before continuing var configErrors = toolsConfig.Validate(); if (configErrors.Count > 0) { foreach (var error in configErrors) { Debug.LogError(error); } return; } var schemaCompilerPath = GetSchemaCompilerPath(); var logfilePath = toolsConfig.DefaultCodegenLogPath; var codegenArgs = new List <string> { $"--json-dir=\"{ImprobableJsonDir}\"", $"--schema-compiler-path=\"{schemaCompilerPath}\"", $"--worker-json-dir=\"{WorkerJsonPath}\"", $"--log-file=\"{logfilePath}\"", $"--descriptor-dir=\"{toolsConfig.DescriptorOutputDir}\"", $"--native-output-dir=\"{toolsConfig.FullCodegenOutputPath}\"" }; if (toolsConfig.VerboseLogging) { codegenArgs.Add("--verbose"); } // Add user defined schema directories codegenArgs.AddRange(toolsConfig.SchemaSourceDirs .Select(schemaDir => $"--schema-path=\"{Path.GetFullPath(schemaDir)}\"")); // Add package schema directories codegenArgs.AddRange(FindDirInPackages(SchemaPackageDir) .Select(directory => $"--schema-path=\"{directory}\"")); codegenArgs.AddRange(toolsConfig.SerializationOverrides .Select(@override => $"--serialization-override=\"{@override}\"")); var codegenArgsString = string.Join(" ", codegenArgs); // For dotnet run / visual studio try { var csprojXml = XDocument.Load(CodegenExe); var projectNode = csprojXml.Element("Project"); var propertyGroup = projectNode.Element("PropertyGroup"); var args = propertyGroup.Element("StartArguments"); args?.Remove(); propertyGroup.Add(XElement.Parse($"<StartArguments>{codegenArgsString}</StartArguments>")); csprojXml.Save(CodegenExe); } catch (Exception e) { throw new Exception($"Unable to add run configuration to '{CodegenExe}'.", e); } // For jetbrains rider var runConfigPath = Path.Combine(CodegenExeDirectory, ".idea", ".idea.CodeGen", ".idea", "runConfigurations"); try { Directory.CreateDirectory(runConfigPath); using (var w = new StreamWriter(Path.Combine(runConfigPath, "CodeGen.xml"), append: false)) { w.Write($@" <component name=""ProjectRunConfigurationManager""> <configuration default=""false"" name=""CodeGen"" type=""DotNetProject"" factoryName="".NET Project""> <option name=""PROJECT_PATH"" value=""$PROJECT_DIR$/CodeGen/CodeGen.csproj"" /> <option name=""PROJECT_KIND"" value=""DotNetCore"" /> <option name=""PROGRAM_PARAMETERS"" value=""{codegenArgsString.Replace("\"", """)}"" /> </configuration> </component> "); } } catch (Exception e) { throw new Exception($"Unable to generate Rider run configuration at '{runConfigPath}'.", e); } }
private static void Generate() { try { if (!Common.CheckDependencies()) { return; } if (!File.Exists(CodegenExe)) { SetupProject(); } EditorApplication.LockReloadAssemblies(); Profiler.BeginSample("Add modules"); UpdateModules(); Profiler.EndSample(); Profiler.BeginSample("Code generation"); var schemaCompilerPath = SchemaCompilerPath; switch (Application.platform) { case RuntimePlatform.WindowsEditor: schemaCompilerPath = Path.ChangeExtension(schemaCompilerPath, ".exe"); break; case RuntimePlatform.LinuxEditor: case RuntimePlatform.OSXEditor: RedirectedProcess.Command("chmod") .WithArgs("+x", $"\"{schemaCompilerPath}\"") .InDirectory(Path.GetFullPath(Path.Combine(Application.dataPath, ".."))) .Run(); break; default: throw new PlatformNotSupportedException( $"The {Application.platform} platform does not support code generation."); } var workerJsonPath = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); var toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); var loggerOutputPath = Path.GetFullPath(Path.Combine(toolsConfig.CodegenLogOutputDir, "codegen-output.log")); using (new ShowProgressBarScope("Generating code...")) { ResetCodegenLogCounter(); var exitCode = RedirectedProcess.Command(Common.DotNetBinary) .WithArgs(ConstructArgs(CodegenExe, schemaCompilerPath, workerJsonPath, loggerOutputPath)) .RedirectOutputOptions(OutputRedirectBehaviour.None) .AddOutputProcessing(ProcessDotnetOutput) .AddOutputProcessing(ProcessCodegenOutput) .Run(); var numWarnings = codegenLogCounts[CodegenLogLevel.Warn]; var numErrors = codegenLogCounts[CodegenLogLevel.Error] + codegenLogCounts[CodegenLogLevel.Fatal]; if (exitCode.ExitCode != 0 || numErrors > 0) { if (!Application.isBatchMode) { Debug.LogError("Code generation failed! Please check the console for more information."); EditorApplication.delayCall += () => { if (File.Exists(loggerOutputPath)) { var option = EditorUtility.DisplayDialogComplex("Generate Code", $"Code generation failed with {numWarnings} warnings and {numErrors} errors!\n\nPlease check the code generation logs for more information: {loggerOutputPath}", "Open logfile", "Close", ""); switch (option) { // Open logfile case 0: Application.OpenURL(loggerOutputPath); break; // Close case 1: // Alt case 2: break; default: throw new ArgumentOutOfRangeException("Unrecognised option"); } } else { DisplayGeneralFailure(); } }; } } else { if (numWarnings > 0) { Debug.LogWarning($"Code generation completed successfully with {numWarnings} warnings. Please check the logs for more information: {loggerOutputPath}"); } else { Debug.Log("Code generation complete!"); } File.WriteAllText(StartupCodegenMarkerFile, string.Empty); } } AssetDatabase.Refresh(); } catch (Exception e) { Debug.LogException(e); } finally { Profiler.EndSample(); EditorApplication.UnlockReloadAssemblies(); } }
public static void LaunchLocalDeployment() { BuildConfig(); GdkToolsConfiguration toolsConfig = GdkToolsConfiguration.GetOrCreateInstance(); var command = Common.SpatialBinary; #if UNITY_EDITOR_OSX var commandArgs = $"local launch --enable_pre_run_check=false --snapshot '{toolsConfig.CustomSnapshotPath}' --experimental_runtime={toolsConfig.RuntimeVersion}"; #else var commandArgs = $"local launch --enable_pre_run_check=false --snapshot \"{toolsConfig.CustomSnapshotPath}\" --experimental_runtime={toolsConfig.RuntimeVersion}"; #endif var runtimeIp = EditorPrefs.GetString(Common.RuntimeIpEditorPrefKey); if (!string.IsNullOrEmpty(runtimeIp)) { commandArgs = $"{commandArgs} --runtime_ip={runtimeIp}"; } if (Application.platform == RuntimePlatform.OSXEditor) { command = "osascript"; commandArgs = $@"-e 'tell application ""Terminal"" activate do script ""cd {Common.SpatialProjectRootDir} && {Common.SpatialBinary} {commandArgs}"" end tell'"; } var processInfo = new ProcessStartInfo(command, commandArgs) { CreateNoWindow = false, UseShellExecute = true, WorkingDirectory = Common.SpatialProjectRootDir }; var process = Process.Start(processInfo); if (process == null) { Debug.LogError("Failed to start SpatialOS locally."); return; } process.EnableRaisingEvents = true; process.Exited += (sender, args) => { // N.B. This callback is run on a different thread. if (process.ExitCode == 0) { return; } var logPath = Path.Combine(Common.SpatialProjectRootDir, "logs"); var latestLogFile = Directory.GetFiles(logPath, "spatial_*.log") .Select(f => new FileInfo(f)) .OrderBy(f => f.LastWriteTimeUtc).LastOrDefault(); if (latestLogFile == null) { Debug.LogError($"Could not find a spatial log file in {logPath}."); return; } var message = $"For more information, check the spatial local launch logfile: {latestLogFile.FullName}"; if (WasProcessKilled(process)) { Debug.Log(message); } else { Debug.LogError($"Errors occured - {message}"); } process.Dispose(); process = null; }; }