public static async Task BringUpToDate(string branch, string expectedVersion, string updateReason) { string currentVersion = versionRegistry.GetString("VersionGuid"); if (currentVersion != expectedVersion) { DialogResult check = MessageBox.Show ( "Roblox Studio is out of date!\n" + updateReason + "\nWould you like to update now?", "Out of date!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning ); if (check == DialogResult.Yes) { StudioBootstrapper installer = new StudioBootstrapper(false); await installer.RunInstaller(branch, false); installer.Dispose(); } } }
public static void ApplyFlags() { var configs = new List <string>(); foreach (string flagName in flagRegistry.GetSubKeyNames()) { RegistryKey flagKey = flagRegistry.OpenSubKey(flagName); string type = flagKey.GetString("Type"), value = flagKey.GetString("Value"); if (type.EndsWith("String", Program.StringFormat)) { value = $"\"{value.Replace("\"", "")}\""; } configs.Add($"\t\"{flagName}\": {value}"); } ; string json = "{\r\n" + string.Join(",\r\n", configs) + "\r\n}"; string studioDir = StudioBootstrapper.GetStudioDirectory(); string clientSettings = Path.Combine(studioDir, "ClientSettings"); Directory.CreateDirectory(clientSettings); string filePath = Path.Combine(clientSettings, "ClientAppSettings.json"); File.WriteAllText(filePath, json); }
public static async Task BringUpToDate(string branch, string expectedVersion, string updateReason) { string currentVersion = Program.VersionRegistry.GetString("VersionGuid"); if (currentVersion != expectedVersion) { DialogResult check = MessageBox.Show ( "Roblox Studio is out of date!\n" + updateReason + "\nWould you like to update now?", "Out of date!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning ); if (check == DialogResult.Yes) { var bootstrapper = new StudioBootstrapper() { Branch = branch }; using (var installer = new BootstrapperForm(bootstrapper)) { var bootstrap = installer.Bootstrap(); await bootstrap.ConfigureAwait(true); } } } }
public static async Task PatchExplorerIcons() { string studioDir = StudioBootstrapper.GetStudioDirectory(); string iconPath = Path.Combine(studioDir, iconManifest); var getPatched = Task.Run(() => getPatchedExplorerIcons()); Image patched = await getPatched.ConfigureAwait(true); patched.Save(iconPath); }
private static string getExplorerIconDir() { string studioBin = StudioBootstrapper.GetStudioDirectory(); string explorerBin = Path.Combine(studioBin, "ExplorerIcons"); if (!Directory.Exists(explorerBin)) { Directory.CreateDirectory(explorerBin); } return(explorerBin); }
private async void editFVariables_Click(object sender, EventArgs e) { bool allow = true; // Create a warning prompt if the user hasn't disabled this warning. var warningDisabled = Program.GetBool("Disable Flag Warning"); if (!warningDisabled) { SystemSounds.Hand.Play(); allow = false; using (Form warningPrompt = createFlagWarningPrompt()) { warningPrompt.ShowDialog(); if (warningPrompt.DialogResult == DialogResult.Yes) { Program.SetValue("Disable Flag Warning", warningPrompt.Enabled); allow = true; } } } if (allow) { string branch = getSelectedBranch(); Enabled = false; UseWaitCursor = true; var infoTask = StudioBootstrapper.GetCurrentVersionInfo(branch); var info = await infoTask.ConfigureAwait(true); Hide(); var updateTask = BootstrapperForm.BringUpToDate(branch, info.Guid, "Some newer flags might be missing."); await updateTask.ConfigureAwait(true); using (FlagEditor editor = new FlagEditor()) editor.ShowDialog(); Show(); BringToFront(); Enabled = true; UseWaitCursor = false; } }
private async void editFVariables_Click(object sender, EventArgs e) { bool allow = true; // Create a warning prompt if the user hasn't disabled this warning. var warningDisabled = Program.GetBool("Disable Flag Warning"); if (!warningDisabled) { SystemSounds.Hand.Play(); allow = false; Form warningPrompt = createFlagWarningPrompt(); warningPrompt.ShowDialog(); DialogResult result = warningPrompt.DialogResult; if (result == DialogResult.Yes) { Program.SetValue("Disable Flag Warning", warningPrompt.Enabled); allow = true; } } if (allow) { string branch = getSelectedBranch(); Enabled = false; UseWaitCursor = true; ClientVersionInfo info = await StudioBootstrapper.GetCurrentVersionInfo(branch); Hide(); await StudioBootstrapper.BringUpToDate(branch, info.Guid, "某些新参数可能无法在旧版本使用!"); FlagEditor editor = new FlagEditor(branch); editor.ShowDialog(); Show(); BringToFront(); Enabled = true; UseWaitCursor = false; } }
public BootstrapperForm(StudioBootstrapper bootstrapper, bool exitWhenClosed = false) { Contract.Requires(bootstrapper != null); InitializeComponent(); Bootstrapper = bootstrapper; exitOnClose = exitWhenClosed; bootstrapper.EchoFeed += new MessageEventHandler(Bootstrapper_EchoFeed); bootstrapper.StatusChanged += new MessageEventHandler(Bootstrapper_StatusChanged); bootstrapper.ProgressChanged += new ChangeEventHandler <int>(Bootstrapper_ProgressChanged); bootstrapper.ProgressBarStyleChanged += new ChangeEventHandler <ProgressBarStyle>(Bootstrapper_ProgressBarStyleChanged); Show(); BringToFront(); }
private static Image getExplorerIcons() { string manifestHash = manifestRegistry.GetString(iconManifest); string currentHash = infoRegistry.GetString("LastClassIconhash"); if (currentHash != manifestHash) { string studioDir = StudioBootstrapper.GetStudioDirectory(); UpdateExplorerIcons(studioDir); infoRegistry.SetValue("LastClassIconHash", manifestHash); } string imagePath = infoRegistry.GetString("SourceLocation"); Image explorerIcons = Image.FromFile(imagePath); numIcons = explorerIcons.Width / iconSize; return(explorerIcons); }
public static async Task <StudioDeployLogs> Get(string branch) { StudioDeployLogs logs = null; if (LogCache.ContainsKey(branch)) { logs = LogCache[branch]; } else { logs = new StudioDeployLogs(branch); } var getDeployHistory = HistoryCache.GetDeployHistory(branch); string deployHistory = await getDeployHistory.ConfigureAwait(false); if (logs.LastDeployHistory != deployHistory) { int maxVersion = int.MaxValue; if (branch == "roblox") { string binaryType = StudioBootstrapper.GetStudioBinaryType(); var getInfo = ClientVersionInfo.Get(binaryType); var info = await getInfo.ConfigureAwait(false); int version = info.Version .Split('.') .Select(int.Parse) .Skip(1) .First(); maxVersion = version; } logs.LastDeployHistory = deployHistory; logs.UpdateLogs(deployHistory, maxVersion); } return(logs); }
public static async Task <bool> PatchExplorerIcons() { bool success = false; try { string studioDir = StudioBootstrapper.GetStudioDirectory(); string iconPath = Path.Combine(studioDir, iconManifest); Image patched = await Task.Factory.StartNew(getPatchedExplorerIcons); patched.Save(iconPath); } catch (Exception e) { Console.WriteLine("An error occurred while trying to patch the explorer icons: {0}", e.Message); } return(success); }
private async void editExplorerIcons_Click(object sender, EventArgs e) { Enabled = false; UseWaitCursor = true; string branch = (string)branchSelect.SelectedItem; ClientVersionInfo info = await StudioBootstrapper.GetCurrentVersionInfo(branch); Hide(); await StudioBootstrapper.BringUpToDate(branch, info.Guid, "The class icons may have received an update."); var editor = new ClassIconEditor(branch); editor.ShowDialog(); Show(); BringToFront(); Enabled = true; UseWaitCursor = false; }
public static bool ApplyFlags() { try { List <string> configs = new List <string>(); foreach (string flagName in flagRegistry.GetSubKeyNames()) { RegistryKey flagKey = flagRegistry.OpenSubKey(flagName); string type = flagKey.GetString("Type"), value = flagKey.GetString("Value"); if (type.EndsWith("String")) { value = $"\"{value.Replace("\"", "")}\""; } configs.Add($"\t\"{flagName}\": {value}"); } ; string json = "{\r\n" + string.Join(",\r\n", configs) + "\r\n}"; string studioDir = StudioBootstrapper.GetStudioDirectory(); string clientSettings = Path.Combine(studioDir, "ClientSettings"); Directory.CreateDirectory(clientSettings); string filePath = Path.Combine(clientSettings, "ClientAppSettings.json"); File.WriteAllText(filePath, json); return(true); } catch { Console.WriteLine("Failed to apply flag editor configuration!"); return(false); } }
private async void editExplorerIcons_Click(object sender, EventArgs e) { Enabled = false; UseWaitCursor = true; string branch = (string)branchSelect.SelectedItem; Hide(); var infoTask = StudioBootstrapper.GetCurrentVersionInfo(branch); var info = await infoTask.ConfigureAwait(true); var updateTask = BootstrapperForm.BringUpToDate(branch, info.VersionGuid, "The class icons may have received an update."); await updateTask.ConfigureAwait(true); using (var editor = new ClassIconEditor()) editor.ShowDialog(); Show(); BringToFront(); Enabled = true; UseWaitCursor = false; }
private async void initializeEditor() { string localAppData = Environment.GetEnvironmentVariable("LocalAppData"); string settingsDir = Path.Combine(localAppData, "Roblox", "ClientSettings"); string settingsPath = Path.Combine(settingsDir, "StudioAppSettings.json"); string lastExecVersion = versionRegistry.GetString("LastExecutedVersion"); string versionGuid = versionRegistry.GetString("VersionGuid"); if (lastExecVersion != versionGuid) { // Reset the settings file. Directory.CreateDirectory(settingsDir); File.WriteAllText(settingsPath, ""); // Create some system events for studio so we can hide the splash screen. SystemEvent start = new SystemEvent("FFlagExtract"); SystemEvent show = new SystemEvent("NoSplashScreen"); // Run Roblox Studio briefly so we can update the settings file. ProcessStartInfo studioStartInfo = new ProcessStartInfo() { FileName = StudioBootstrapper.GetStudioPath(), Arguments = $"-startEvent {start.Name} -showEvent {show.Name}" }; Process studio = Process.Start(studioStartInfo); await start.WaitForEvent(); FileInfo info = new FileInfo(settingsPath); // Wait for the settings path to be written. while (info.Length == 0) { await Task.Delay(30); info.Refresh(); } // Nuke studio and flag the version we updated with. versionRegistry.SetValue("LastExecutedVersion", versionGuid); studio.Kill(); } // Initialize flag browser string[] flagNames = flagRegistry.GetSubKeyNames(); string settings = File.ReadAllText(settingsPath); var json = Program.ReadJsonDictionary(settings); int numFlags = json.Count; var flagSetup = new List <FVariable>(numFlags); var autoComplete = new AutoCompleteStringCollection(); foreach (var pair in json) { string key = pair.Key, value = pair.Value; FVariable flag = new FVariable(key, value); autoComplete.Add(flag.Name); flagSetup.Add(flag); if (flagNames.Contains(flag.Name)) { // Update what the flag should be reset to if removed? RegistryKey flagKey = flagRegistry.GetSubKey(flag.Name); flagKey.SetValue("Reset", value); // Set the flag's editor. flag.SetEditor(flagKey); } } flagSearchFilter.AutoCompleteCustomSource = autoComplete; allFlags = flagSetup .OrderBy(flag => flag.Name) .ToList(); refreshFlags(); // Initialize override table. overrideTable = new DataTable(); foreach (DataGridViewColumn column in overrideDataGridView.Columns) { overrideTable.Columns.Add(column.DataPropertyName); } DataView overrideView = new DataView(overrideTable); overrideView.Sort = "Name"; foreach (string flagName in flagNames) { if (flagLookup.ContainsKey(flagName)) { int index = flagLookup[flagName]; FVariable flag = flags[index]; addFlagOverride(flag, true); } } overrideStatus.Visible = true; overrideDataGridView.DataSource = overrideView; }
private async void launchStudio_Click(object sender = null, EventArgs e = null) { string branch = getSelectedBranch(); var bootstrapper = new StudioBootstrapper { ForceInstall = forceRebuild.Checked, ApplyModManagerPatches = true, SetStartEvent = true, Branch = branch }; Hide(); using (var installer = new BootstrapperForm(bootstrapper)) { var install = installer.Bootstrap(); await install.ConfigureAwait(true); } string studioRoot = StudioBootstrapper.GetStudioDirectory(); string modPath = getModPath(); string[] modFiles = Directory.GetFiles(modPath, "*.*", SearchOption.AllDirectories); foreach (string modFile in modFiles) { try { byte[] fileContents = File.ReadAllBytes(modFile); FileInfo modFileControl = new FileInfo(modFile); string relativeFile = modFile.Replace(modPath, studioRoot); string relativeDir = Directory .GetParent(relativeFile) .ToString(); if (!Directory.Exists(relativeDir)) { Directory.CreateDirectory(relativeDir); } if (File.Exists(relativeFile)) { byte[] relativeContents = File.ReadAllBytes(relativeFile); if (fileContents.SequenceEqual(relativeContents)) { continue; } modFileControl.CopyTo(relativeFile, true); continue; } File.WriteAllBytes(relativeFile, fileContents); } catch { Console.WriteLine("Failed to overwrite {0}!", modFile); } } var robloxStudioInfo = new ProcessStartInfo() { FileName = StudioBootstrapper.GetStudioPath(), Arguments = $"-startEvent {StudioBootstrapper.StartEvent}" }; if (args != null) { string firstArg = args[0]; if (firstArg != null && firstArg.StartsWith("roblox-studio", Program.StringFormat)) { // Arguments were passed by URI. var argMap = new Dictionary <string, string>(); foreach (string commandPair in firstArg.Split('+')) { if (commandPair.Contains(':')) { string[] kvPair = commandPair.Split(':'); string key = kvPair[0]; string val = kvPair[1]; if (key == "gameinfo") { // The user is authenticating. This argument is a special case. robloxStudioInfo.Arguments += " -url https://www.roblox.com/Login/Negotiate.ashx -ticket " + val; } else { argMap.Add(key, val); robloxStudioInfo.Arguments += " -" + key + ' ' + val; } } } if (argMap.ContainsKey("launchmode") && !argMap.ContainsKey("task")) { string launchMode = argMap["launchmode"]; if (launchMode == "plugin") { string pluginId = argMap["pluginid"]; robloxStudioInfo.Arguments += "-task InstallPlugin -pluginId " + pluginId; } else if (launchMode == "edit") { robloxStudioInfo.Arguments += "-task EditPlace"; } } } else { // Arguments were passed directly. for (int i = 0; i < args.Length; i++) { string arg = args[i]; if (arg.Contains(' ')) { arg = $"\"{arg}\""; } robloxStudioInfo.Arguments += ' ' + arg; } } } if (openStudioDirectory.Checked) { Process.Start(studioRoot); Environment.Exit(0); } else { string currentVersion = versionRegistry.GetString("VersionGuid"); versionRegistry.SetValue("LastExecutedVersion", currentVersion); Process.Start(robloxStudioInfo); } }
private async void ClassIconEditor_Load(object sender, EventArgs e) { Enabled = false; UseWaitCursor = true; EventHandler iconBtnClicked = new EventHandler(onIconBtnClicked); string studioPath = StudioBootstrapper.GetStudioPath(); showModifiedIcons = explorerRegistry.GetBool("ShowModifiedIcons"); darkTheme = explorerRegistry.GetBool("DarkTheme"); showModified.Checked = showModifiedIcons; themeSwitcher.Text = "Theme: " + (darkTheme ? "Dark" : "Light"); selectedIcon.BackColor = (darkTheme ? THEME_DARK_NORMAL : THEME_LIGHT_NORMAL); selectedIcon.Refresh(); int extraSlots = getExtraItemSlots(); Image defaultIcon = null; SuspendLayout(); var load = Task.Run(() => { Image explorerIcons = getExplorerIcons(); // Load Main Icons for (int i = 0; i < numIcons; i++) { Button iconBtn = createIconButton(iconBtnClicked); Bitmap icon = new Bitmap(iconSize, iconSize); iconLookup.Add(icon); Rectangle srcRect = new Rectangle(i * iconSize, 0, iconSize, iconSize); Rectangle iconRect = new Rectangle(0, 0, iconSize, iconSize); using (Graphics graphics = Graphics.FromImage(icon)) graphics.DrawImage(explorerIcons, iconRect, srcRect, GraphicsUnit.Pixel); if (defaultIcon == null) { defaultIcon = icon; } buttonLookup.Add(iconBtn); iconBtnIndex.Add(iconBtn, i); if (showModifiedIcons) { iconBtn.BackgroundImage = getIconForIndex(i); } else { iconBtn.BackgroundImage = icon; } AddControlAcrossThread(iconContainer, iconBtn); } // Load Extra Slots for (int i = 0; i < maxExtraIcons; i++) { int slot = numIcons + i; Button iconBtn = createIconButton(iconBtnClicked); iconBtn.Visible = (i < extraSlots); string fileName = getExplorerIconPath(slot); if (i < extraSlots && File.Exists(fileName)) { Image icon = getIconForIndex(slot); iconBtn.BackgroundImage = icon; } iconLookup.Add(defaultIcon); buttonLookup.Add(iconBtn); iconBtnIndex.Add(iconBtn, slot); AddControlAcrossThread(iconContainer, iconBtn); } explorerIcons.Dispose(); }); await load.ConfigureAwait(true); setSelectedIndex(0); ResumeLayout(); itemSlots.Value = extraSlots; header.Text = "Select Icon"; iconWatcher = new FileSystemWatcher(getExplorerIconDir()) { Filter = "*.png", EnableRaisingEvents = true }; iconWatcher.Created += safeFileEventHandler(onFileCreated); iconWatcher.Changed += safeFileEventHandler(onFileChanged); iconWatcher.Deleted += safeFileEventHandler(onFileDeleted); Enabled = true; UseWaitCursor = false; }