private async void initializeEditor() { string localAppData = Environment.GetEnvironmentVariable("LocalAppData"); string settingsPath = Path.Combine(localAppData, "Roblox", "ClientSettings", "StudioAppSettings.json"); string lastExecVersion = versionRegistry.GetString("LastExecutedVersion"); string versionGuid = versionRegistry.GetString("VersionGuid"); if (lastExecVersion != versionGuid || settingsPath == "") { // Run Roblox Studio briefly so we can update the settings file. ProcessStartInfo studioStartInfo = new ProcessStartInfo() { CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, FileName = RobloxStudioInstaller.GetStudioPath() }; Process studio = Process.Start(studioStartInfo); DateTime startTime = DateTime.Now; FileInfo info = new FileInfo(settingsPath); // Wait for the settings path file to exist or for it to be updated. while (!info.Exists || info.LastWriteTime.Ticks < startTime.Ticks) { await Task.Delay(100); info.Refresh(); } // Wait just a moment so we don't access the file while its in a write lock. await Task.Delay(500); // Should be good now. Nuke studio and flag the version we updated with. versionRegistry.SetValue("LastExecutedVersion", versionGuid); studio.Kill(); } string[] flagNames = flagRegistry.GetSubKeyNames(); string settings = File.ReadAllText(settingsPath) .Replace('\r', ' ').Replace('\n', ' ') .Replace("{\"", "").Replace("\"}", ""); // Initialize Flag Table flagTable = createFlagDataTable(); var splitPairs = new string[1] { ",\"" }; foreach (string kvPairStr in settings.Split(splitPairs, StringSplitOptions.None)) { string[] kvPair = kvPairStr .Replace("\"", "") .Split(':'); if (kvPair.Length == 2) { string key = kvPair[0].Replace('"', ' ').Trim(); string value = kvPair[1].Replace('"', ' ').Trim(); string type = flagPrefixes .Where(pre => key.StartsWith(pre)) .FirstOrDefault(); if (type.Length > 0) { string name = key.Substring(type.Length); flagTable.Rows.Add(name, type, value); if (flagNames.Contains(name)) { // Update what the flag should be reset to if removed? RegistryKey flagKey = flagRegistry.OpenSubKey(name); flagKey.SetValue("Reset", value); } } } } // Setup flag->row lookup table. flagView = initializeDataGridView(flagDataGridView, flagTable); foreach (DataGridViewRow row in flagDataGridView.Rows) { var cells = row.Cells; string name = cells[0].Value as string; string type = cells[1].Value as string; string value = cells[2].Value as string; flagRowLookup.Add(type + name, row); } // Initialize Override Table overrideTable = createFlagDataTable(); initializeDataGridView(overrideDataGridView, overrideTable); foreach (string flagName in flagNames) { RegistryKey flagKey = flagRegistry.GetSubKey(flagName); string name = flagKey.GetString("Name"), type = flagKey.GetString("Type"), value = flagKey.GetString("Value"); addFlagOverride(name, type, value, true); } var columns = overrideDataGridView.Columns; columns[0].ReadOnly = true; columns[1].ReadOnly = true; // Resume layout and enable interaction. flagDataGridView.CurrentCell = flagDataGridView[0, 0]; flagDataGridView.ResumeLayout(); overrideStatus.Visible = true; overrideDataGridView.ResumeLayout(); }
private async void launchStudio_Click(object sender = null, EventArgs e = null) { Hide(); string branch = (string)branchSelect.SelectedItem; RobloxStudioInstaller installer = new RobloxStudioInstaller(forceRebuild.Checked); await installer.RunInstaller(branch); string studioRoot = RobloxStudioInstaller.GetStudioDirectory(); string modPath = getModPath(); string[] studioFiles = Directory.GetFiles(studioRoot); 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)) { modFileControl.CopyTo(relativeFile, true); } } else { File.WriteAllBytes(relativeFile, fileContents); } } catch { Console.WriteLine("Failed to overwrite {0}!", modFile); } } // Hack in the metadata plugin. // This is used to provide an end-point to custom StarterScripts that are trying to fork what branch they are on. // It creates a BindableFunction inside of the ScriptContext called GetModManagerBranch, which returns the branch set in the launcher. try { Assembly self = Assembly.GetExecutingAssembly(); string metaScript; using (Stream stream = self.GetManifestResourceStream("RobloxStudioModManager.Resources.ModManagerMetadata.lua")) using (StreamReader reader = new StreamReader(stream)) { metaScript = reader.ReadToEnd(); metaScript = metaScript.Replace("%MOD_MANAGER_VERSION%", '"' + branch + '"'); // TODO: Make this something more generic? } string dir = Path.Combine(studioRoot, "BuiltInPlugins"); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } string metaScriptFile = Path.Combine(dir, "__rbxModManagerMetadata.lua"); FileInfo info = new FileInfo(metaScriptFile); if (info.Exists) { info.Attributes = FileAttributes.Normal; } File.WriteAllText(metaScriptFile, metaScript); // Make the file as readonly so that it (hopefully) won't be messed with. // I can't hide the file because Roblox Studio will ignore it. // If someone has the file open with write permissions, it will fail to write. info.Attributes = FileAttributes.ReadOnly; } catch { Console.WriteLine("Failed to write __rbxModManagerMetadata.lua"); } var robloxStudioInfo = new ProcessStartInfo(); robloxStudioInfo.FileName = RobloxStudioInstaller.GetStudioPath(); if (args != null) { string firstArg = args[0]; if (firstArg != null && firstArg.StartsWith("roblox-studio")) { // 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")) { robloxStudioInfo.Arguments += "-task "; string launchMode = argMap["launchmode"]; string addToArgs = ""; if (launchMode == "plugin") { addToArgs = "InstallPlugin"; } else if (launchMode == "edit") { addToArgs = "EditPlace"; } robloxStudioInfo.Arguments += addToArgs; } } else { // Arguments were passed directly. string fullArg = string.Join(" ", args); robloxStudioInfo.Arguments += fullArg; } } if (openStudioDirectory.Checked) { Process.Start(studioRoot); } else { string currentVersion = versionRegistry.GetString("VersionGuid"); versionRegistry.SetValue("LastExecutedVersion", currentVersion); Process.Start(robloxStudioInfo); } Environment.Exit(0); }
private async void ExplorerIconEditor_Load(object sender, EventArgs e) { Enabled = false; UseWaitCursor = true; EventHandler iconBtnClicked = new EventHandler(onIconBtnClicked); string studioPath = RobloxStudioInstaller.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(); await 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)) { try { Image icon = getIconForIndex(slot); iconBtn.BackgroundImage = icon; } catch (Exception ex) { Console.WriteLine("Couldn't load extra slot {0} - {1}", i, ex.Message); } } iconLookup.Add(defaultIcon); buttonLookup.Add(iconBtn); iconBtnIndex.Add(iconBtn, slot); addControlAcrossThread(iconContainer, iconBtn); } explorerIcons.Dispose(); }); setSelectedIndex(0); ResumeLayout(); itemSlots.Value = extraSlots; header.Text = "Select Icon"; iconWatcher = new FileSystemWatcher(getExplorerIconDir()); iconWatcher.Filter = "*.png"; iconWatcher.EnableRaisingEvents = true; iconWatcher.Created += safeFileEventHandler(onFileCreated); iconWatcher.Changed += safeFileEventHandler(onFileChanged); iconWatcher.Deleted += safeFileEventHandler(onFileDeleted); Enabled = true; UseWaitCursor = false; }