/// <summary> /// Constructs a new instance of <c>WorkerConfiguration</c>. /// </summary> /// <param name="data">User-configured data used to configure the worker.</param> /// <param name="commandLineArguments"> /// A list of arguments specified on the command line. /// If null, defaults to /// <example>global::System.Environment.GetCommandLineArgs()</example> /// </param> public WorkerConfiguration(WorkerConfigurationData data, IList <string> commandLineArguments = null) { if (commandLineArguments == null) { commandLineArguments = global::System.Environment.GetCommandLineArgs(); } Debug.LogFormat("Command line {0}", string.Join(" ", commandLineArguments.ToArray())); commandLineDictionary = CommandLineUtil.ParseCommandLineArgs(commandLineArguments); ProjectName = string.Empty; if (Application.isEditor) { // Read ProjectName from the spatialos.json file, if not already specified. // This is only done in Editor mode, as we do not expect spatialos.json to exist outside of dev environment. if (!commandLineDictionary.ContainsKey(CommandLineConfigNames.ProjectName) && !commandLineDictionary.ContainsKey(CommandLineConfigNames.AppName)) { try { ProjectName = ProjectDescriptor.Load().Name; } catch (Exception e) { Debug.LogErrorFormat("Cannot read project name from '{0}'. You will not be able to connect to a deployment. Underlying error: {1}", ProjectDescriptor.ProjectDescriptorPath, e); } } } var defaultWorkerPlatform = data.SpatialOsApplication.WorkerPlatform; #pragma warning disable 618 var workerPlatformString = GetObsoleteAndCurrentCommandLineValue(EditableConfigNames.WorkerType, EditableConfigNames.EngineType, string.Empty); #pragma warning restore 618 if (!string.IsNullOrEmpty(workerPlatformString)) { defaultWorkerPlatform = WorkerTypeUtils.FromWorkerName(workerPlatformString); } var workerName = WorkerTypeUtils.ToWorkerName(data.SpatialOsApplication.WorkerPlatform); appName = GetCommandLineValue(CommandLineConfigNames.AppName, string.Empty); ProjectName = GetCommandLineValue(CommandLineConfigNames.ProjectName, ProjectName); AssemblyName = GetCommandLineValue(EditableConfigNames.AssemblyName, data.SpatialOsApplication.AssemblyName); DeploymentId = GetCommandLineValue(EditableConfigNames.DeploymentId, data.SpatialOsApplication.DeploymentId); DeploymentTag = GetCommandLineValue(EditableConfigNames.DeploymentTag, data.SpatialOsApplication.DeploymentTag); #pragma warning disable 618 WorkerId = GetObsoleteAndCurrentCommandLineValue(EditableConfigNames.WorkerId, EditableConfigNames.EngineId, workerName + Guid.NewGuid()); #pragma warning restore 618 WorkerPlatform = defaultWorkerPlatform; #pragma warning disable 618 EntityCreationLimitPerFrame = GetCommandLineValue(EditableConfigNames.EntityCreationLimitPerFrame, data.Unity.EntityCreationLimitPerFrame); #pragma warning restore 618 InfraServiceUrl = GetCommandLineValue(EditableConfigNames.InfraServiceUrl, data.Debugging.InfraServiceUrl); ReceptionistHost = GetCommandLineValue(EditableConfigNames.ReceptionistHost, data.Networking.ReceptionistHost); ReceptionistPort = GetCommandLineValue(EditableConfigNames.ReceptionistPort, data.Networking.ReceptionistPort); LinkProtocol = GetCommandLineValue(EditableConfigNames.LinkProtocol, data.Networking.LinkProtocol); LocatorHost = GetCommandLineValue(EditableConfigNames.LocatorHost, data.Networking.LocatorHost); LoginToken = GetLoginTokenConfig(data); ProtocolLogPrefix = GetCommandLineValue(EditableConfigNames.ProtocolLogPrefix, data.Debugging.ProtocolLogPrefix); ProtocolLoggingOnStartup = GetCommandLineValue(EditableConfigNames.ProtocolLoggingOnStartup, data.Debugging.ProtocolLoggingOnStartup); ProtocolLogMaxFileBytes = GetCommandLineValue(EditableConfigNames.ProtocolLogMaxFileBytes, data.Debugging.ProtocolLogMaxFileBytes); RaknetHeartbeatTimeoutMillis = GetCommandLineValue(EditableConfigNames.RaknetHeartbeatTimeoutMillis, data.Networking.RaknetHeartbeatTimeoutMillis); ReceiveQueueCapacity = data.Networking.ReceiveQueueCapacity; SendQueueCapacity = data.Networking.SendQueueCapacity; SteamToken = GetCommandLineValue(EditableConfigNames.SteamToken, data.Networking.SteamToken); TcpMultiplexLevel = GetCommandLineValue(EditableConfigNames.TcpMultiplexLevel, data.Networking.TcpMultiplexLevel); UseExternalIp = GetCommandLineValue(CommandLineConfigNames.UseExternalIpForBridge, Defaults.UseExternalIp) == false; // DEV-1120: The flag is flipped for legacy reasons. UseInstrumentation = GetCommandLineValue(EditableConfigNames.UseInstrumentation, data.Debugging.UseInstrumentation); UsePrefabPooling = GetCommandLineValue(EditableConfigNames.UsePrefabPooling, data.Unity.UsePrefabPooling); LogDebugToSpatialOs = GetCommandLineValue(EditableConfigNames.LogDebugToSpatialOs, data.Debugging.LogDebugToSpatialOs); LogAssertToSpatialOs = GetCommandLineValue(EditableConfigNames.LogAssertToSpatialOs, data.Debugging.LogAssertToSpatialOs); LogWarningToSpatialOs = GetCommandLineValue(EditableConfigNames.LogWarningToSpatialOs, data.Debugging.LogWarningToSpatialOs); LogErrorToSpatialOs = GetCommandLineValue(EditableConfigNames.LogErrorToSpatialOs, data.Debugging.LogErrorToSpatialOs); LogExceptionToSpatialOs = GetCommandLineValue(EditableConfigNames.LogExceptionToSpatialOs, data.Debugging.LogExceptionToSpatialOs); if (string.IsNullOrEmpty(ProjectName)) { throw new ArgumentException(string.Format("The ProjectName must be set with {0}, or via command-line argument +{1}", Path.GetFileName(ProjectDescriptor.ProjectDescriptorPath), CommandLineConfigNames.ProjectName)); } if (Application.isEditor == false) { PrintWorkerConfigurationSettings(); } }
public static void RunDeployment(DeployParams Params) { string PluginPath = Params.PluginPath; ConsoleUtils.WriteHeader("Begin Deployment"); Console.WriteLine("Deploying plugin at " + PluginPath); // Get uplugin path string UPluginPath = DeployUtils.FindUPluginPath(PluginPath); Console.WriteLine("Identified " + Path.GetFileName(UPluginPath) + " as plugin definition"); string PluginName = DeployUtils.FindPluginName(PluginPath); // Deserialize uplugin PluginDescriptor PluginDef = JsonConvert.DeserializeObject <PluginDescriptor>(File.ReadAllText(UPluginPath)); string ProjectPath = DeployUtils.FindHostProjectPath(PluginPath); string UProjectPath = DeployUtils.FindHostUProjectPath(PluginPath); Console.WriteLine("Identified " + Path.GetFileName(UProjectPath) + " as host project definition"); ProjectDescriptor ProjectDef = ProjectDescriptor.Load(UProjectPath); if (!ProjectDef.HasPluginEnabled(PluginName)) { throw new Exception(".uproject does not list " + PluginName + " as an enabled plugin dependency"); } // Trim patch version if (PluginDef.EngineVersion != null) { string[] PluginEngineVersionSplit = PluginDef.EngineVersion.Split('.'); string PluginEngineVersion = PluginEngineVersionSplit[0] + '.' + PluginEngineVersionSplit[1]; // Check engine versions match if (PluginEngineVersion != ProjectDef.EngineAssociation) { throw new Exception("Project engine version " + ProjectDef.EngineAssociation + " does not match plugin engine version " + PluginDef.EngineVersion); } } else { bool Continue = ConsoleUtils.PromptBool(".uplugin has no EngineVersion. Project engine version is " + ProjectDef.EngineAssociation + ". Continue?", true); if (!Continue) { return; } } string branchName = VersionControlUtils.GetBranchName(ProjectPath); string archiveVersionName = null; if (Params.Archive) { // Use the version if on any of these branches string[] standardBranchNames = { "master", "develop", "development" }; if (!branchName.StartsWith("version/", StringComparison.InvariantCultureIgnoreCase) && !standardBranchNames.Contains(branchName, StringComparer.InvariantCultureIgnoreCase)) { Console.WriteLine("On branch '" + branchName + "' which isn't a version or standard branch"); archiveVersionName = branchName.Replace("/", "-"); } else { archiveVersionName = PluginDef.VersionName; } Console.WriteLine("Archive version name is '" + archiveVersionName + "'"); } // Begin work ConsoleUtils.WriteHeader("Preparing plugin"); // Get engine path string EnginePath = ProjectDef.GetEngineInstall().InstallDirectory; string EnginePluginsMarketplacePath = Path.Combine(EnginePath, @"Engine\Plugins\Marketplace"); string EnginePluginsMarketplacePluginPath = Path.Combine(EnginePluginsMarketplacePath, Path.GetFileName(PluginPath)); // Delete plugin from engine if installed version exists ConsoleFileUtils.DeleteDirectoryIfExists(EnginePluginsMarketplacePluginPath); //string WorkingTempPath = Path.Combine(Path.GetTempPath(), "MarketplaceDeploy", PluginName); //string WorkingTempPath = Path.Combine(Path.GetPathRoot(Path.GetTempPath()), "MarketplaceDeploy", PluginName); string WorkingTempPath = Path.Combine(Path.GetPathRoot(Path.GetTempPath()), PluginName); Directory.CreateDirectory(WorkingTempPath); // Build plugin ConsoleUtils.WriteHeader("Building plugin"); string PluginBuildPath = Path.Combine(WorkingTempPath, @"PluginBuild", PluginName); ConsoleFileUtils.DeleteDirectoryIfExists(PluginBuildPath); ProcessStartInfo PluginBuildStartInfo = new ProcessStartInfo() { Arguments = "BuildPlugin -Plugin=\"" + UPluginPath + "\" -Package=\"" + PluginBuildPath + "\" -Rocket -VS2019", FileName = Path.Combine(EnginePath, @"Engine\Build\BatchFiles\RunUAT.bat"), UseShellExecute = false }; Process PluginBuildProcess = new Process(); PluginBuildProcess.StartInfo = PluginBuildStartInfo; PluginBuildProcess.Start(); PluginBuildProcess.WaitForExit(); if (PluginBuildProcess.ExitCode > 0) { throw new Exception("Plugin build failed"); } Console.WriteLine("Plugin build complete"); // Copy config directory to plugin build because the build process doesn't do so string SourcePluginConfigPath = Path.Combine(PluginPath, @"Config"); string PluginBuildConfigPath = Path.Combine(PluginBuildPath, @"Config"); ConsoleFileUtils.CopyDirectory(SourcePluginConfigPath, PluginBuildConfigPath); // Copy plugin into engine where the marketplace installs it Console.WriteLine("Copying to Engine/Plugins/Marketplace"); ConsoleFileUtils.DeleteDirectoryIfExists(EnginePluginsMarketplacePluginPath); ConsoleFileUtils.CopyDirectory(PluginBuildPath, EnginePluginsMarketplacePluginPath); // Set up host project ConsoleUtils.WriteHeader("Preparing host project"); string UProjectFilename = Path.GetFileName(UProjectPath); string ProjectName = Path.GetFileNameWithoutExtension(UProjectPath); string ExampleProjectBuildPath = Path.Combine(WorkingTempPath, @"ExampleProject"); ConsoleFileUtils.DeleteDirectoryIfExists(ExampleProjectBuildPath); ConsoleFileUtils.CopySubdirectory(ProjectPath, ExampleProjectBuildPath, "Content"); ConsoleFileUtils.CopySubdirectory(ProjectPath, ExampleProjectBuildPath, "Config"); if (!Params.RemoveSource) { ConsoleFileUtils.CopySubdirectory(ProjectPath, ExampleProjectBuildPath, "Source"); } string ProjectIcon = ProjectName + ".png"; if (File.Exists(ProjectIcon)) { ConsoleFileUtils.CopyFile(ProjectPath, ExampleProjectBuildPath, ProjectIcon); } // Copy uproject JObject UProjectContents = JObject.Parse(File.ReadAllText(UProjectPath)); // Remove modules property if applicable before building if (Params.RemoveSource) { UProjectContents.Remove("Modules"); } string ExampleProjectBuildUProjectPath = Path.Combine(ExampleProjectBuildPath, UProjectFilename); File.WriteAllText(ExampleProjectBuildUProjectPath, UProjectContents.ToString()); // Build example project without archiving to test that it can package with plugin installed to engine // It's worth doing this to test for build or packaging issues that might only happen using installed plugin Console.WriteLine("Building example project with installed plugin"); string InstalledPluginTestBuildArchivePath = Path.Combine(WorkingTempPath, @"InstalledPluginTestBuild"); ConsoleFileUtils.DeleteDirectoryIfExists(InstalledPluginTestBuildArchivePath); ProcessStartInfo InstalledPluginTestBuildStartInfo = new ProcessStartInfo() { Arguments = "BuildCookRun -project=\"" + ExampleProjectBuildUProjectPath + "\" -noP4 -platform=Win64 -clientconfig=Development -serverconfig=Development -cook -allmaps -build -stage " + DeployUtils.GetPakString(Params.Pak) + "-archive -archivedirectory=\"" + InstalledPluginTestBuildArchivePath + "\"", FileName = Path.Combine(EnginePath, @"Engine\Build\BatchFiles\RunUAT.bat"), UseShellExecute = false }; Process InstalledPluginTestBuildProcess = new Process(); InstalledPluginTestBuildProcess.StartInfo = InstalledPluginTestBuildStartInfo; InstalledPluginTestBuildProcess.Start(); InstalledPluginTestBuildProcess.WaitForExit(); if (InstalledPluginTestBuildProcess.ExitCode > 0) { throw new Exception("Example project build with installed plugin failed"); } // Uninstall plugin from engine because test has completed // Now we'll be using the plugin in the project directory instead Console.WriteLine("Uninstall from Engine/Plugins/Marketplace"); ConsoleFileUtils.DeleteDirectoryIfExists(EnginePluginsMarketplacePluginPath); // Copy plugin to example project to prepare for package string ExampleProjectPluginPath = Path.Combine(ExampleProjectBuildPath, "Plugins", Path.GetFileName(PluginPath)); ConsoleFileUtils.CopyDirectory(PluginBuildPath, ExampleProjectPluginPath); // Package game for demo ConsoleUtils.WriteHeader("Packaging host project for demo"); string DemoExePath = Path.Combine(WorkingTempPath, @"DemoExe"); ConsoleFileUtils.DeleteDirectoryIfExists(DemoExePath); ProcessStartInfo DemoExeStartInfo = new ProcessStartInfo() { Arguments = "BuildCookRun -project=\"" + ExampleProjectBuildUProjectPath + "\" -noP4 -platform=Win64 -clientconfig=Development -serverconfig=Development -cook -allmaps -build -stage " + DeployUtils.GetPakString(Params.Pak) + "-archive -archivedirectory=\"" + DemoExePath + "\"", FileName = Path.Combine(EnginePath, @"Engine\Build\BatchFiles\RunUAT.bat"), UseShellExecute = false }; Process DemoExeBuildProcess = new Process(); DemoExeBuildProcess.StartInfo = DemoExeStartInfo; DemoExeBuildProcess.Start(); DemoExeBuildProcess.WaitForExit(); if (DemoExeBuildProcess.ExitCode > 0) { throw new Exception("Example project build failed"); } // Archiving if (Params.Archive) { ConsoleUtils.WriteHeader("Archiving"); string ArchivePrefix = PluginName + "_" + archiveVersionName + "_"; string ArchivePath = Path.Combine(WorkingTempPath, "Archives"); Directory.CreateDirectory(ArchivePath); // Archive plugin build Console.WriteLine("Archiving plugin build"); string PluginBuildZipPath = Path.Combine(ArchivePath, ArchivePrefix + "PluginBuild.zip"); ConsoleFileUtils.DeleteFile(PluginBuildZipPath); ZipFile.CreateFromDirectory(PluginBuildPath, PluginBuildZipPath, CompressionLevel.Optimal, true); // Archive demo exe Console.WriteLine("Archiving demo"); string DemoExeZipPath = Path.Combine(ArchivePath, ArchivePrefix + "DemoExe.zip"); ConsoleFileUtils.DeleteFile(DemoExeZipPath); ZipFile.CreateFromDirectory(Path.Combine(DemoExePath, "WindowsNoEditor"), DemoExeZipPath); // Archive example project Console.WriteLine("Archiving example project"); // First delete any extra directories string[] AllowedExampleProjectSubDirectoryNames = { "Content", "Config" }; ConsoleFileUtils.DeleteOtherSubdirectories(ExampleProjectBuildPath, AllowedExampleProjectSubDirectoryNames); // If we didn't remove source before, remove it now since we never want it in the example project if (!Params.RemoveSource) { UProjectContents.Remove("Modules"); File.WriteAllText(ExampleProjectBuildUProjectPath, UProjectContents.ToString()); } string ExampleProjectZipPath = Path.Combine(ArchivePath, ArchivePrefix + "ExampleProject.zip"); ConsoleFileUtils.DeleteFile(ExampleProjectZipPath); ZipFile.CreateFromDirectory(ExampleProjectBuildPath, ExampleProjectZipPath); // Archive plugin for submission Console.WriteLine("Archiving plugin"); // Copy plugin build to submission so that we can prepare archive for submission without ruining build string PluginSubmissionPath = Path.Combine(WorkingTempPath, @"PluginSubmission", PluginName); ConsoleFileUtils.DeleteDirectoryIfExists(PluginSubmissionPath); ConsoleFileUtils.CopyDirectory(PluginBuildPath, PluginSubmissionPath); string[] AllowedPluginSubmissionSubDirectoryNames = { "Source", "Resources", "Content", "Config" }; ConsoleFileUtils.DeleteOtherSubdirectories(PluginSubmissionPath, AllowedPluginSubmissionSubDirectoryNames); string PluginSubmissionZipPath = Path.Combine(ArchivePath, ArchivePrefix + "PluginSubmission.zip"); ConsoleFileUtils.DeleteFile(PluginSubmissionZipPath); ZipFile.CreateFromDirectory(PluginSubmissionPath, PluginSubmissionZipPath, CompressionLevel.Optimal, true); // Upload to staging folder on drive if (Params.Upload) { ConsoleUtils.WriteHeader("Uploading"); Console.WriteLine("Uploading plugin"); DriveIntegration.UploadFile(PluginSubmissionZipPath); Console.WriteLine("Uploading example project"); DriveIntegration.UploadFile(ExampleProjectZipPath); Console.WriteLine("Uploading demo"); DriveIntegration.UploadFile(DemoExeZipPath); } else { Console.WriteLine("Skipping upload"); } } else { Console.WriteLine("Skipping archive"); } ConsoleUtils.WriteHeader("MarketplaceDeployConsole finished successfully"); }