Beispiel #1
0
 private static IEnumerable <string> ScanForGameDataFiles()
 {
     return(from id in AssetDatabase.FindAssets("t:DefaultAsset")
            let path = FileAndPathUtils.MakeProjectRelative(AssetDatabase.GUIDToAssetPath(id))
                       where path != null && IsGameDataFile(path)
                       select path);
 }
 static MonoRuntimeInformation()
 {
     if (RuntimeInformation.IsWindows)
     {
         MonoExecutableName  = "mono.exe";
         MonoDefaultLocation = Path.Combine(FileAndPathUtils.GetProgramFilesx86(), @"Mono\bin");
     }
     else if (RuntimeInformation.IsOsx)
     {
         MonoExecutableName  = "mono";
         MonoDefaultLocation = @"/Library/Frameworks/Mono.framework/Commands";
     }
     else
     {
         MonoExecutableName  = "mono";
         MonoDefaultLocation = @"/usr/bin";
     }
 }
Beispiel #3
0
        private static IEnumerable DownloadCharonAsync(Action <string, float> progressCallback = null)
        {
            var checkRequirements = CharonCli.CheckRequirementsAsync();

            yield return(checkRequirements);

            var checkResult = checkRequirements.GetResult();

            if (checkResult == RequirementsCheckResult.MissingRuntime)
            {
                yield return(UpdateRuntimeWindow.ShowAsync());
            }

            var currentVersion = default(Version);
            var charonPath     = Path.GetFullPath(Settings.CharonPath);
            var toolName       = Path.GetFileNameWithoutExtension(Path.GetFileName(charonPath));

            if (File.Exists(charonPath))
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_CHECKING_TOOLS_VERSION, 0.05f);
                }

                var checkToolsVersion = CharonCli.GetVersionAsync();
                yield return(checkToolsVersion.IgnoreFault());

                currentVersion = checkToolsVersion.HasErrors ? default(Version) : checkToolsVersion.GetResult();
            }

            if (progressCallback != null)
            {
                progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_GETTING_AVAILABLE_BUILDS, 0.10f);
            }

            var getBuildsAsync = UpdateServerCli.GetBuilds(UpdateServerCli.PRODUCT_CHARON);

            yield return(getBuildsAsync.IgnoreFault());

            if (getBuildsAsync.HasErrors)
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f);
                }

                Debug.LogError(string.Format("Failed to get builds list from server. Error: {0}", getBuildsAsync.Error.Unwrap().Message));
                yield break;
            }

            var builds          = getBuildsAsync.GetResult();
            var buildsByVersion = builds.ToDictionary(b => b.Version);
            var lastBuild       = builds.OrderByDescending(b => b.Version).FirstOrDefault();

            if (lastBuild == null)
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f);
                }

                if (Settings.Current.Verbose)
                {
                    Debug.Log(string.Format("No builds of {0} are available.", toolName));
                }
                yield break;
            }

            var currentBuild = currentVersion != null?builds.FirstOrDefault(b => b.Version == currentVersion) : null;

            var lastVersion     = lastBuild.Version;
            var isMissing       = File.Exists(charonPath);
            var actualHash      = isMissing || currentBuild == null ? null : FileAndPathUtils.ComputeHash(charonPath, currentBuild.HashAlgorithm);
            var isCorrupted     = currentBuild != null && string.Equals(currentBuild.Hash, actualHash, StringComparison.OrdinalIgnoreCase) == false;
            var expectedVersion = string.IsNullOrEmpty(Settings.Current.EditorVersion) ? default(Version) : new Version(Settings.Current.EditorVersion);

            if (!isMissing && !isCorrupted && expectedVersion == currentVersion && currentVersion != null)
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f);
                }

                if (Settings.Current.Verbose)
                {
                    Debug.Log(string.Format("{0} version '{1}' is expected and file is not corrupted.", toolName, currentVersion));
                }
                yield break;
            }

            var versionToDownload = expectedVersion ?? lastVersion;

            if (buildsByVersion.ContainsKey(versionToDownload) == false)
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f);
                }

                Debug.LogError(string.Format("Build of {0} with version '{1}' is not available to download.", toolName, versionToDownload));
                yield break;
            }

            if (progressCallback != null)
            {
                progressCallback(string.Format(Resources.UI_UNITYPLUGIN_PROGRESS_DOWNLOADINGS, 0, 0), 0.10f);
            }

            var downloadPath  = Path.GetTempFileName();
            var downloadAsync = UpdateServerCli.DownloadBuild(UpdateServerCli.PRODUCT_CHARON, versionToDownload, downloadPath, progressCallback);

            yield return(downloadAsync.IgnoreFault());

            if (downloadAsync.HasErrors)
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f);
                }

                Debug.LogError(string.Format("Failed to download build of {0} with version '{1}'.{2}{3}", toolName, versionToDownload, Environment.NewLine, downloadAsync.Error.Unwrap()));
                yield break;
            }

            GameDataEditorWindow.FindAllAndClose();

            try
            {
                if (File.Exists(charonPath))
                {
                    File.Delete(charonPath);
                }
                if (Directory.Exists(charonPath))
                {
                    Directory.Delete(charonPath);
                }

                var toolsDirectory = Path.GetDirectoryName(charonPath) ?? "";
                if (Directory.Exists(toolsDirectory) == false)
                {
                    Directory.CreateDirectory(toolsDirectory);
                }

                File.Move(downloadPath, charonPath);

                // ensure config file
                var charonConfigPath = charonPath + ".config";
                if (File.Exists(charonConfigPath) == false)
                {
                    var embeddedConfigStream = typeof(Menu).Assembly.GetManifestResourceStream("GameDevWare.Charon.Charon.exe.config");
                    if (embeddedConfigStream != null)
                    {
                        using (embeddedConfigStream)
                            using (var configFileStream = File.Create(charonConfigPath, 8 * 1024, FileOptions.SequentialScan))
                            {
                                var buffer = new byte[8 * 1024];
                                var read   = 0;
                                while ((read = embeddedConfigStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    configFileStream.Write(buffer, 0, read);
                                }
                            }
                    }
                }
            }
            catch (Exception moveError)
            {
                Debug.LogWarning(string.Format("Failed to move downloaded file from '{0}' to {1}. {2}.", downloadPath, charonPath, moveError.Message));
                Debug.LogError(moveError);
            }
            finally
            {
                try { if (File.Exists(downloadPath))
                      {
                          File.Delete(downloadPath);
                      }
                }
                catch { /* ignore */ }
            }

            if (File.Exists(charonPath))
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_CHECKING_TOOLS_VERSION, 0.95f);
                }

                var checkToolsVersion = CharonCli.GetVersionAsync();
                yield return(checkToolsVersion.IgnoreFault());

                currentVersion = checkToolsVersion.HasErrors ? default(Version) : checkToolsVersion.GetResult();
            }

            Settings.Current.EditorVersion = currentVersion != null?currentVersion.ToString() : null;

            Settings.Current.Save();

            Debug.Log(string.Format("{1} version is '{0}'. Download is complete.", currentVersion, Path.GetFileName(charonPath)));

            if (progressCallback != null)
            {
                progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f);
            }
        }
Beispiel #4
0
        internal static Promise <Process> Listen(string gameDataPath, string lockFilePath, int port, bool shadowCopy = true, Action <string, float> progressCallback = null)
        {
            if (string.IsNullOrEmpty(gameDataPath))
            {
                throw new ArgumentException("Value cannot be null or empty.", "gameDataPath");
            }
            if (string.IsNullOrEmpty(lockFilePath))
            {
                throw new ArgumentException("Value cannot be null or empty.", "lockFilePath");
            }
            if (port <= 0 || port > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException("port");
            }

            var charonPath = Path.GetFullPath(Settings.CharonPath);

            if (File.Exists(gameDataPath) == false)
            {
                throw new IOException(string.Format("File '{0}' doesn't exists.", gameDataPath));
            }
            if (File.Exists(charonPath) == false)
            {
                throw new IOException(string.Format("File '{0}' doesn't exists.", charonPath));
            }

            if (shadowCopy)
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_COPYING_EXECUTABLE, 0.10f);
                }

                var charonMd5       = FileAndPathUtils.ComputeHash(charonPath);
                var shadowDirectory = Path.GetFullPath(Path.Combine(TempDirectory, charonMd5));
                if (Directory.Exists(shadowDirectory) == false)
                {
                    if (Settings.Current.Verbose)
                    {
                        Debug.Log("Making shadow copy of '" + Path.GetFileName(charonPath) + "' to '" + shadowDirectory + "'.");
                    }

                    Directory.CreateDirectory(shadowDirectory);

                    var shadowCharonPath = Path.Combine(shadowDirectory, Path.GetFileName(charonPath));
                    File.Copy(charonPath, shadowCharonPath, overwrite: true);

                    var configPath       = charonPath + ".config";
                    var configShadowPath = shadowCharonPath + ".config";
                    if (File.Exists(configPath))
                    {
                        if (Settings.Current.Verbose)
                        {
                            Debug.Log("Making shadow copy of '" + Path.GetFileName(configPath) + "' to '" + shadowDirectory + "'.");
                        }

                        File.Copy(configPath, configShadowPath);
                    }
                    else
                    {
                        Debug.LogWarning("Missing required configuration file at '" + configPath + "'.");
                    }

                    charonPath = shadowCharonPath;
                }
                else
                {
                    charonPath = Path.Combine(shadowDirectory, Path.GetFileName(charonPath));
                }
            }
            if (progressCallback != null)
            {
                progressCallback(Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_LAUNCHING_EXECUTABLE, 0.30f);
            }
            var unityPid            = Process.GetCurrentProcess().Id;
            var scriptingAssemblies = FindAndLoadScriptingAssemblies(gameDataPath);
            var runTask             = CommandLine.Run(
                new RunOptions
                (
                    charonPath,

                    RunOptions.FlattenArguments(
                        "SERVE", Path.GetFullPath(gameDataPath),
                        "--port", port.ToString(),
                        "--watchPid", unityPid.ToString(),
                        "--lockFile", Path.GetFullPath(lockFilePath),
                        "--environment", "Unity",
                        "--extensions", Settings.SupportedExtensions,
                        "--scriptAssemblies", scriptingAssemblies,
                        Settings.Current.Verbose ? "--verbose" : ""
                        )
                )
            {
                RequireDotNetRuntime  = true,
                CaptureStandardError  = false,
                CaptureStandardOutput = false,
                ExecutionTimeout      = TimeSpan.Zero,
                WaitForExit           = false,
                StartInfo             =
                {
                    EnvironmentVariables =
                    {
                        { "CHARON_APP_DATA", Settings.GetLocalUserDataPath() },
                        { "CHARON_SERVER",   Settings.Current.ServerAddress  }
                    }
                }
            }
                );

            if (progressCallback != null)
            {
                runTask.ContinueWith(_ => progressCallback(Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_LAUNCHING_EXECUTABLE, 1.0f));
            }

            return(runTask.ContinueWith(t => t.GetResult().Process));
        }