示例#1
0
        public static async Task <List <PackageManifest> > Get(string branch, string versionGuid)
        {
            var result = new List <PackageManifest>();

            string pkgManifestUrl = $"https://s3.amazonaws.com/setup.{branch}.com/{versionGuid}-rbxPkgManifest.txt";
            string pkgManifestData;

            using (WebClient http = new WebClient())
                pkgManifestData = await http.DownloadStringTaskAsync(pkgManifestUrl);

            using (StringReader reader = new StringReader(pkgManifestData))
            {
                string version = reader.ReadLine();

                if (version != "v0")
                {
                    string errorMsg = $"Unexpected package manifest version: {version} (expected v0!)\n" +
                                      "Please contact CloneTrooper1019 if you see this error.";

                    throw new NotSupportedException(errorMsg);
                }

                while (true)
                {
                    try
                    {
                        string fileName  = reader.ReadLine();
                        string signature = reader.ReadLine();

                        int packedSize = int.Parse(reader.ReadLine());
                        int size       = int.Parse(reader.ReadLine());

                        if (fileName.EndsWith(".zip"))
                        {
                            var pkgManifest = new PackageManifest()
                            {
                                Name       = fileName,
                                Branch     = branch,
                                Signature  = signature,
                                PackedSize = packedSize,
                                Size       = size
                            };

                            result.Add(pkgManifest);
                        }
                    }
                    catch
                    {
                        break;
                    }
                }
            }

            return(result);
        }
示例#2
0
        public async Task RunInstaller(string branch)
        {
            restore();

            setStatus("Checking for updates");
            echo("Checking build installation...");

            string currentBranch  = Program.GetString("BuildBranch", "roblox");
            string currentVersion = versionRegistry.GetString("VersionGuid");

            bool   shouldInstall = (forceInstall || currentBranch != branch);
            string fastVersion   = await GetFastVersionGuid(currentBranch);

            if (branch == "roblox")
            {
                buildVersion = fastVersion;
            }

            ClientVersionInfo versionInfo = null;

            if (shouldInstall || fastVersion != currentVersion)
            {
                if (currentBranch != "roblox")
                {
                    echo("Possible update detected, verifying...");
                }

                versionInfo = await GetCurrentVersionInfo(branch, fastVersion);

                buildVersion = versionInfo.Guid;
            }
            else
            {
                buildVersion = fastVersion;
            }

            if (currentVersion != buildVersion || shouldInstall)
            {
                echo("This build needs to be installed!");
                bool studioClosed = await shutdownStudioProcesses();

                if (studioClosed)
                {
                    string binaryType = GetStudioBinaryType();
                    string studioDir  = GetStudioDirectory();
                    string versionId  = versionInfo.Version;

                    restore();
                    setStatus($"Installing Version {versionId} of Roblox Studio...");

                    var taskQueue = new List <Task>();

                    echo("Grabbing package manifest...");
                    List <PackageManifest> pkgManifest = await PackageManifest.Get(branch, buildVersion);

                    echo("Grabbing file manifest...");
                    fileManifest = await FileManifest.Get(branch, buildVersion);

                    progressBar.Maximum = 1;
                    progressBar.Value   = 0;

                    progressBar.Style = ProgressBarStyle.Continuous;
                    progressBar.Refresh();

                    foreach (PackageManifest package in pkgManifest)
                    {
                        Task installer = Task.Run(() => installPackage(package));
                        taskQueue.Add(installer);
                    }

                    await Task.WhenAll(taskQueue.ToArray());

                    echo("Writing AppSettings.xml...");

                    string appSettings = Path.Combine(studioDir, "AppSettings.xml");
                    File.WriteAllText(appSettings, appSettingsXml);

                    setStatus("Deleting unused files...");
                    await deleteUnusedFiles();

                    progressBar.Style = ProgressBarStyle.Marquee;
                    progressBar.Refresh();

                    Program.SetValue("BuildBranch", branch);

                    versionRegistry.SetValue("Version", versionId);
                    versionRegistry.SetValue("VersionGuid", buildVersion);
                }
                else
                {
                    progressBar.Style = ProgressBarStyle.Marquee;
                    progressBar.Refresh();

                    echo("Update cancelled. Launching on current branch and version.");
                }
            }
            else
            {
                echo("This version of Roblox Studio has been installed!");
            }

            setStatus("Configuring Roblox Studio...");

            echo("Updating registry protocols...");
            Program.UpdateStudioRegistryProtocols();

            if (exitWhenClosed)
            {
                echo("Applying flag configuration...");
                FlagEditor.ApplyFlags();

                echo("Patching explorer icons...");
                await ExplorerIconEditor.PatchExplorerIcons();
            }

            setStatus("Starting Roblox Studio...");
            echo("Roblox Studio is up to date!");

            await Task.Delay(1000);
        }
示例#3
0
        private async Task installPackage(PackageManifest package)
        {
            string studioDir = GetStudioDirectory();
            string downloads = getDirectory(studioDir, "downloads");

            string pkgName = package.Name;
            string branch  = package.Branch;

            string oldSig = pkgRegistry.GetString(pkgName);
            string newSig = package.Signature;

            if (oldSig == newSig && !forceInstall)
            {
                echo($"Package '{pkgName}' hasn't changed between builds, skipping.");
                return;
            }

            string zipFileUrl     = $"https://s3.amazonaws.com/setup.{branch}.com/{buildVersion}-{pkgName}";
            string zipExtractPath = Path.Combine(downloads, package.Name);

            incrementProgressBarMax(package.Size);
            echo($"Installing package {zipFileUrl}");

            var localHttp = new WebClient();

            localHttp.Headers.Set("UserAgent", "Roblox");

            // Download the zip file package.
            byte[] fileContents = await localHttp.DownloadDataTaskAsync(zipFileUrl);

            // If the size of the file we downloaded does not match the packed size specified
            // in the manifest, then this file has been tampered with.

            if (fileContents.Length != package.PackedSize)
            {
                throw new InvalidDataException($"{package.Name} expected packed size: {package.PackedSize} but got: {fileContents.Length}");
            }

            using (MemoryStream fileBuffer = new MemoryStream(fileContents))
            {
                // Compute the MD5 signature of this zip file, and make sure it matches with the
                // signature specified in the package manifest.
                string checkSig = computeSignature(fileBuffer);

                if (checkSig != newSig)
                {
                    throw new InvalidDataException($"{package.Name} expected signature: {newSig} but got: {checkSig}");
                }

                // Write the zip file.
                File.WriteAllBytes(zipExtractPath, fileContents);
            }

            ZipArchive archive      = ZipFile.OpenRead(zipExtractPath);
            string     localRootDir = null;

            var reprocess = new Dictionary <ZipArchiveEntry, string>();

            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                if (entry.Length > 0)
                {
                    string newFileSig = null;

                    // If we have figured out what our root directory is, try to resolve
                    // what the signature of this file is.

                    if (localRootDir != null)
                    {
                        var fileSignatures = fileManifest.FileToSignature;

                        string filePath    = entry.FullName.Replace('/', '\\');
                        bool   hasFilePath = fileSignatures.ContainsKey(filePath);

                        // If we can't find this file in the signature lookup table,
                        // try appending the local directory to it. This resolves some
                        // edge cases relating to the fixFilePath function above.

                        if (!hasFilePath)
                        {
                            filePath    = localRootDir + filePath;
                            hasFilePath = fileSignatures.ContainsKey(filePath);
                        }

                        // If we can find this file path in the file manifest, then we will
                        // use its pre-computed signature to check if the file has changed.

                        newFileSig = hasFilePath ? fileSignatures[filePath] : null;
                    }

                    // If we couldn't pre-determine the file signature from the manifest,
                    // then we have to compute it manually. This is slower.

                    if (newFileSig == null)
                    {
                        newFileSig = computeSignature(entry);
                    }

                    // Now check what files this signature corresponds with.
                    if (fileManifest.SignatureToFiles.ContainsKey(newFileSig))
                    {
                        // Write this package to each of the files specified.
                        List <string> files = fileManifest.SignatureToFiles[newFileSig];

                        foreach (string file in files)
                        {
                            // Write the file from this signature.
                            writePackageFile(studioDir, pkgName, file, newFileSig, entry);

                            if (localRootDir == null)
                            {
                                string filePath  = fixFilePath(pkgName, file);
                                string entryPath = entry.FullName.Replace('/', '\\');

                                if (filePath.EndsWith(entryPath))
                                {
                                    // We can infer what the root extraction
                                    // directory is for the files in this package!
                                    localRootDir = filePath.Replace(entryPath, "");
                                }
                            }
                        }
                    }
                    else
                    {
                        string file = entry.FullName;

                        if (localRootDir == null)
                        {
                            // Check back on this file after we extract the regular files,
                            // so we can make sure this is extracted to the correct directory.
                            reprocess.Add(entry, newFileSig);
                        }
                        else
                        {
                            // Append the local root directory.
                            file = localRootDir + file;
                            writePackageFile(studioDir, pkgName, file, newFileSig, entry);
                        }
                    }
                }
            }

            // Process any files that we deferred from writing immediately.
            foreach (ZipArchiveEntry entry in reprocess.Keys)
            {
                string file       = entry.FullName;
                string newFileSig = reprocess[entry];

                if (localRootDir != null)
                {
                    file = localRootDir + file;
                }

                writePackageFile(studioDir, pkgName, file, newFileSig, entry);
            }

            // Update the signature in the package registry so we can check
            // if this zip file needs to be updated in future versions.
            pkgRegistry.SetValue(pkgName, package.Signature);
        }
示例#4
0
        public async Task RunInstaller(string branch, bool setStartEvent = false)
        {
            restore();

            setStatus("检查更新中");
            echo("检查该构建版本是否可安装...");

            string currentBranch  = Program.GetString("BuildBranch", "roblox");
            string currentVersion = versionRegistry.GetString("VersionGuid");

            bool   shouldInstall = (forceInstall || currentBranch != branch);
            string fastVersion   = await GetFastVersionGuid(currentBranch);

            ClientVersionInfo versionInfo = null;

            if (shouldInstall || fastVersion != currentVersion)
            {
                if (currentBranch != "roblox")
                {
                    echo("发现已有更新,验证中...");
                }

                versionInfo = await GetCurrentVersionInfo(branch, fastVersion);

                buildVersion = versionInfo.Guid;
            }
            else
            {
                buildVersion = fastVersion;
            }

            if (currentVersion != buildVersion || shouldInstall)
            {
                echo("此构建版本需要安装!");
                bool studioClosed = await shutdownStudioProcesses();

                if (studioClosed)
                {
                    string binaryType = GetStudioBinaryType();
                    string studioDir  = GetStudioDirectory();
                    string versionId  = versionInfo.Version;

                    restore();
                    setStatus($"正在安装版本为 {versionId} 的 Roblox Studio...");

                    var taskQueue = new List <Task>();
                    writtenFiles = new HashSet <string>();

                    echo("正在获取版本元信息...");
                    var pkgManifest = await PackageManifest.Get(branch, buildVersion);

                    echo("正在获取文件元信息...");
                    fileManifest = await FileManifest.Get(branch, buildVersion);

                    progressBar.Maximum = 5000;
                    progressBar.Value   = 0;

                    progressBar.Style = ProgressBarStyle.Continuous;
                    progressBar.Refresh();

                    foreach (var package in pkgManifest)
                    {
                        Task installer = Task.Run(() => installPackage(branch, package));
                        taskQueue.Add(installer);
                    }

                    await Task.WhenAll(taskQueue);

                    echo("正在写入 AppSettings.xml...");

                    string appSettings = Path.Combine(studioDir, "AppSettings.xml");
                    File.WriteAllText(appSettings, appSettingsXml);

                    setStatus("正在搜索未使用的文件...");
                    await deleteUnusedFiles();

                    progressBar.Style = ProgressBarStyle.Marquee;
                    progressBar.Refresh();

                    Program.SetValue("BuildBranch", branch);

                    versionRegistry.SetValue("Version", versionId);
                    versionRegistry.SetValue("VersionGuid", buildVersion);
                }
                else
                {
                    progressBar.Style = ProgressBarStyle.Marquee;
                    progressBar.Refresh();

                    echo("更新已取消,正在启动当前已有分支版本...");
                }
            }
            else
            {
                echo("该版本安装成功!");
            }

            setStatus("正在配置 Roblox Studio...");

            echo("正在更新注册表...");
            Program.UpdateStudioRegistryProtocols();

            if (exitWhenClosed)
            {
                echo("应用参数配置中...");
                FlagEditor.ApplyFlags();

                echo("修改浏览窗口图标中...");
                await ClassIconEditor.PatchExplorerIcons();
            }

            setStatus("正在启动 Roblox Studio...");
            echo("Roblox Studio 已为最新版!");

            if (setStartEvent)
            {
                SystemEvent start = new SystemEvent("RobloxStudioModManagerStart");

                autoExitTask = Task.Run(async() =>
                {
                    bool started = await start.WaitForEvent();
                    start.Close();

                    if (started)
                    {
                        await Task.Delay(500);
                        Application.Exit();
                    }
                });

                StartEvent = start;
            }
        }