private void onHandleCreated(object sender, EventArgs e) { HandleCreated -= onHandleCreated; GUIThread = Thread.CurrentThread; ETGInstallerSettings.Load(); ETGInstallerSettings.Save(); AdvancedAddButton.Click += (object senderObject, EventArgs evArgs) => ETGInstallerSettings.Save(); AdvancedOfflineCheckbox.CheckedChanged += (object senderObject, EventArgs evArgs) => ETGInstallerSettings.Save(); AdvancedAutoRunCheckbox.CheckedChanged += (object senderObject, EventArgs evArgs) => ETGInstallerSettings.Save(); AdvancedBinaryWrappedCheckbox.CheckedChanged += (object senderObject, EventArgs evArgs) => ETGInstallerSettings.Save(); ExePathButton.Click += (object senderObject, EventArgs evArgs) => ETGInstallerSettings.Save(); for (int i = 0; i < AdvancedRemoveButtons.Count; i++) { AdvancedRemoveButtons[i].Click += (object senderObject, EventArgs evArgs) => ETGInstallerSettings.Save(); } if (string.IsNullOrWhiteSpace(ExePathBox.Text)) { Task.Run((Action)ETGFinder.FindETG); } Task.Run((Action)DownloadModsList); }
public InstallerWindow() { Instance = this; HandleCreated += onHandleCreated; OnRobotFrameChangedHandler = new EventHandler(OnRobotFrameChanged); OpenExeDialog = new OpenFileDialog() { Title = "Select " + ETGFinder.MainName, AutoUpgradeEnabled = true, CheckFileExists = true, CheckPathExists = true, ValidateNames = true, Multiselect = false, ShowReadOnly = false, Filter = ETGFinder.MainName + "|" + ETGFinder.MainName, FilterIndex = 0 }; OpenExeDialog.FileOk += (object senderFileOk, CancelEventArgs eFileOk) => Task.Run(() => this.ExeSelected(OpenExeDialog.FileNames[0])); OpenModDialog = new OpenFileDialog() { Title = "Select ETGMod Backend", AutoUpgradeEnabled = true, CheckFileExists = true, CheckPathExists = true, ValidateNames = true, Multiselect = true, ShowReadOnly = false, Filter = "ETGMod DLL|*.mm.dll|ETGMod ZIP|*.zip|All files|*.*", FilterIndex = 0 }; OpenModDialog.FileOk += (object senderFileOk, CancelEventArgs eFileOk) => AddManualPathRows(OpenModDialog.FileNames); Text = "Mod the Gungeon Installer"; if (ETGFinder.Platform.HasFlag(ETGPlatform.Unix)) { FormBorderStyle = FormBorderStyle.Sizable; } else { FormBorderStyle = FormBorderStyle.FixedDialog; } ResizeRedraw = false; MaximizeBox = false; MinimizeBox = true; StartPosition = FormStartPosition.CenterScreen; //Setting the font doesn't change anything... /*PrivateFontCollection pfc = LoadAsset<PrivateFontCollection>("fonts.uni05_53"); * for (int i = 0; i < pfc.Families.Length; i++) { * Console.WriteLine("Font " + i + ": " + pfc.Families[i]); * } * GlobalFont = new Font(pfc.Families[0], 8f);*/ if (GlobalFont == null) { if (ETGFinder.Platform.HasFlag(ETGPlatform.Windows)) { GlobalFont = new Font("Segoe UI", 8f, FontStyle.Regular); } else if (ETGFinder.Platform.HasFlag(ETGPlatform.MacOS)) { GlobalFont = new Font("Lucida Grande", 8f, FontStyle.Regular); // With Helvetica Neue: Erter Tne Girgeor } else { GlobalFont = new Font("DejaVu Sans", 8f, FontStyle.Regular); } } AllowDrop = true; DragDrop += onDragDrop; DragEnter += delegate(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop) && VersionTabs.Enabled) { e.Effect = DragDropEffects.Copy; VersionTabs.SelectedIndex = 2; } }; BackgroundImage = LoadAsset <Image>("background"); BackgroundImageLayout = ImageLayout.Center; RobotImageIdle = LoadAsset <Image>("icons.idle"); RobotImageInstalling = LoadAsset <Image>("icons.installing.gif"); RobotImageError = LoadAsset <Image>("icons.error.gif"); RobotImageFinished = LoadAsset <Image>("icons.finished.gif"); Controls.Add(RobotPictureBox = new PictureBox() { BackColor = Color.Transparent, Image = RobotImageIdle, Bounds = new Rectangle(150, 100, RobotImageIdle.Width, RobotImageIdle.Height) }); //ShuffleIconColors(); OrigIcon = LoadAsset <Bitmap>("icons.icon"); Icon = Icon.FromHandle(OrigIcon.GetHicon()); ResetSize(); SizeChanged += ResetSize; #if !DEBUG Version = new Version(Version.Major, Version.Minor, Version.Build); #endif Controls.Add(new Label() { Bounds = new Rectangle(448, 338, 308, 16), Font = GlobalFont, TextAlign = ContentAlignment.BottomRight, #if DEBUG Text = "DEBUG " + Version.Revision, #else Text = "v" + Version, #endif BackColor = Color.Transparent, ForeColor = Color.FromArgb(127, 0, 0, 0) }); Controls.Add(LogBox = new RichTextBox() { Bounds = new Rectangle(0, 0, 443, 315), Font = GlobalFont, ReadOnly = true, Multiline = true, //ScrollBars = System.Windows.Forms.ScrollBars.Vertical, DetectUrls = true, ShortcutsEnabled = true, BackColor = Color.Black, ForeColor = Color.White, BorderStyle = BorderStyle.None, WordWrap = true, Text = "ETGMod Installer v" + Version + "\n", Visible = false, }); Controls.Add(ViewLogButton = new Button() { Text = "Show log", Font = GlobalFont, Bounds = new Rectangle(0, 316, 442, 40), Visible = true }); ViewLogButton.Click += delegate(object sender, EventArgs e) { ToggleLog(); }; Controls.Add(Progress = new CustomProgress() { Bounds = new Rectangle(448, 313, 312, 24), Font = GlobalFont, Text = "Idle." }); Add(new Label() { Font = GlobalFont, TextAlign = ContentAlignment.MiddleCenter, Text = !ETGFinder.Platform.HasFlag(ETGPlatform.MacOS) ? ("Step 1: Select " + ETGFinder.MainName) : ("Step 1: Drag-n-drop EtG_OSX.app here"), BackColor = Color.Transparent, ForeColor = Color.Black }); Add(ExePathBox = new TextBox() { Font = GlobalFont, ReadOnly = true }); ExePathBox.Width -= 32; Controls.Add(ExePathButton = new Button() { Bounds = new Rectangle(ExePathBox.Bounds.X + ExePathBox.Bounds.Width, ExePathBox.Bounds.Y, 32, ExePathBox.Bounds.Height), Font = GlobalFont, Image = LoadAsset <Image>("icons.open"), ImageAlign = ContentAlignment.MiddleCenter }); ExePathButton.Click += (object senderClick, EventArgs eClick) => OpenExeDialog.ShowDialog(this); AddOffset += 2; Add(ExeStatusLabel = new Label() { Font = GlobalFont, TextAlign = ContentAlignment.MiddleCenter, Text = "No " + ETGFinder.MainName + " selected", BackColor = Color.FromArgb(127, 255, 63, 63), ForeColor = Color.Black }); AddOffset += 2; Add(new Label() { Font = GlobalFont, TextAlign = ContentAlignment.MiddleCenter, Text = "Step 2: Choose your backends", BackColor = Color.Transparent, ForeColor = Color.Black }); Controls.Add(InstallButton = new Button() { Bounds = new Rectangle(448, 313 - 1 - ExePathButton.Size.Height, 312 - 32, ExePathButton.Size.Height), Font = GlobalFont, TextAlign = ContentAlignment.MiddleCenter, Text = "Step 3: Install ETGMod", Enabled = false }); InstallButton.Click += (object senderClick, EventArgs eClick) => { if (ShowLogOnInstall) { ShowLog(); } Task.Run((Action)this.Install); }; Controls.Add(UninstallButton = new Button() { Bounds = new Rectangle(InstallButton.Bounds.X + InstallButton.Bounds.Width, InstallButton.Bounds.Y, 32, InstallButton.Bounds.Height), Font = GlobalFont, Image = LoadAsset <Image>("icons.uninstall"), ImageAlign = ContentAlignment.MiddleCenter }); UninstallButton.Click += (object senderClick, EventArgs eClick) => Task.Run(delegate() { if (ShowLogOnInstall) { ShowLog(); } this.Uninstall(); this.ClearCache(); this.ExeSelected(ExePathBox.Text, " [just uninstalled]"); this.SetMainEnabled(true); }); Controls.Add(VersionTabs = new TabControl() { Bounds = new Rectangle(448, 4 + 26 * AddIndex + AddOffset, 312, InstallButton.Location.Y - (4 + 26 * AddIndex + AddOffset)), Font = GlobalFont, BackColor = Color.Transparent }); if (ETGFinder.Platform.HasFlag(ETGPlatform.MacOS)) { VersionTabs.BackColor = Color.White; // Mono's WinForms implementation on macOS just sucks. VersionTabs.SelectedIndexChanged += delegate(object sender, EventArgs e) { for (int i = 0; i < VersionTabs.TabPages.Count; i++) { if (i == VersionTabs.SelectedIndex) { VersionTabs.TabPages[i].ShowDeep(); continue; } VersionTabs.TabPages[i].HideDeep(); } RefreshManualPanel(); }; } VersionTabs.TabPages.Add(new TabPage("Backends")); VersionTabs.TabPages[0].Controls.Add(APIModsList = new ListBox() { Font = GlobalFont, Dock = DockStyle.Fill, MultiColumn = true, SelectionMode = SelectionMode.MultiExtended }); APIModsList.SelectedValueChanged += delegate(object sender, EventArgs e) { if (!RepoHelper.IsOffline && !APIModsList.SelectedIndices.Contains(0)) { APIModsList.SelectedIndices.Add(0); } }; APIModsList.MultiColumn = false; APIModsList.DrawMode = DrawMode.OwnerDrawFixed; APIModsList.DrawItem += APIModsListDrawItem; VersionTabs.TabPages.Add(new TabPage("Advanced")); VersionTabs.TabPages[1].Controls.Add(AdvancedPanel = new Panel() { Font = GlobalFont, Dock = DockStyle.Fill, AutoScroll = true }); AdvancedPanel.Controls.Add(AdvancedInfoLabel = new Label() { Text = "Note: This isn't where you install mods!", ImageAlign = ContentAlignment.MiddleCenter, TextAlign = ContentAlignment.MiddleCenter, }); AdvancedPanel.Controls.Add(AdvancedAddButton = new Button() { Font = GlobalFont, Image = LoadAsset <Image>("icons.open"), ImageAlign = ContentAlignment.MiddleCenter }); AdvancedAddButton.Click += (object senderClick, EventArgs eClick) => OpenModDialog.ShowDialog(this); AdvancedPanel.Controls.Add(AdvancedLabel = new Label() { Font = GlobalFont, Text = "or drag-and-drop a folder / .zip here", TextAlign = ContentAlignment.MiddleCenter }); AdvancedPanel.Controls.Add(AdvancedAutoRunCheckbox = new CheckBox() { Font = GlobalFont, Text = "CLOSE " + ETGFinder.MainName + " && run when mod installed", TextAlign = ContentAlignment.MiddleCenter }); if (ETGFinder.Platform.HasFlag(ETGPlatform.MacOS)) { AdvancedAutoRunCheckbox.Text = "CLOSE Gungeon && run when mod installed"; } AdvancedPanel.Controls.Add(AdvancedShowLogOnInstallCheckbox = new CheckBox() { Font = GlobalFont, Text = "Automatically show log when installing", TextAlign = ContentAlignment.MiddleCenter }); AdvancedShowLogOnInstallCheckbox.CheckedChanged += delegate(object sender, EventArgs e) { ETGInstallerSettings.Save(); }; AdvancedPanel.Controls.Add(AdvancedOfflineCheckbox = new CheckBox() { Font = GlobalFont, Text = "Offline mode - only use the APIs here", TextAlign = ContentAlignment.MiddleCenter }); AdvancedOfflineCheckbox.CheckedChanged += delegate(object senderCheck, EventArgs eCheck) { ETGModder.IsOffline = RepoHelper.IsOffline = AdvancedOfflineCheckbox.Checked; DownloadModsList(); ETGInstallerSettings.Save(); }; AdvancedPanel.Controls.Add(AdvancedBinaryWrappedCheckbox = new CheckBox() { Font = GlobalFont, Text = ETGFinder.MainName + " is a wrapper, use EtG.bin", TextAlign = ContentAlignment.MiddleCenter }); AdvancedBinaryWrappedCheckbox.CheckedChanged += delegate(object senderCheck, EventArgs eCheck) { ETGFinder.IsBinaryWrapped = AdvancedBinaryWrappedCheckbox.Checked; ETGFinder.FindETG(); ETGInstallerSettings.Save(); }; RefreshManualPanel(); }
public static void ExeSelected(this InstallerWindow ins, string path, string suffix = null) { if (InstallerWindow.InstantClearSymbols != null) { InstallerWindow.Instance.ClearSymbols(InstallerWindow.InstantClearSymbols); InstallerWindow.InstantClearSymbols = null; } if (string.IsNullOrEmpty(path)) { path = null; } string origPath = path; ins.Invoke(delegate() { ins.InstallButton.Enabled = false; ins.ExePathBox.Text = origPath; ins.ExeStatusLabel.Text = "EtG [checking version]"; if (suffix != null) { ins.ExeStatusLabel.Text += suffix; } ins.ExeStatusLabel.BackColor = Color.FromArgb(127, 255, 255, 63); }); if (path != null && (ins.MainMod == null || ins.MainModIn != path)) { if (!Platform.HasFlag(ETGPlatform.MacOS)) { path = Path.Combine(Directory.GetParent(path).FullName, "EtG_Data", "Managed", "Assembly-CSharp.dll"); } else { path = Path.Combine(Directory.GetParent(path).Parent.Parent.FullName, "Resources", "Data", "Managed", "Assembly-CSharp.dll"); } if (!File.Exists(path)) { path = null; } } ins.ModVersion = null; ins.MainMod?.Dispose(); if (path == null) { ins.MainMod = null; ins.Invoke(delegate() { ins.ExeStatusLabel.Text = "No " + MainName + " selected"; ins.ExeStatusLabel.BackColor = Color.FromArgb(127, 255, 63, 63); ins.ExePathBox.Text = ""; ins.InstallButton.Enabled = false; OnExeSelected?.Invoke(false); }); return; } ins.MainMod = new MonoModder() { InputPath = ins.MainModIn = path // Output set when actually patching }; ins.MainMod.SetupETGModder(); ins.MainModDir = Directory.GetParent(ins.MainModIn).FullName; //We want to read the assembly now already. Writing is also handled manually. try { ins.MainMod.Read(false); } catch (BadImageFormatException) { //this is not the assembly we need... ins.ExeSelected(null); return; } /* catch (MonoSymbolFileException) { * // Mono.Cecil keeps the file handle for itself; We need to restart here. * ins.MainMod.Dispose(); * ins.RestartAndClearSymbols(); * return; * }*/catch (Exception e) { //Something went wrong. ins.Log("Something went horribly wrong after you've selected ").LogLine(MainName); ins.LogLine("Blame Zatherz and send him this log ASAP!"); ins.Log("PATH: ").LogLine(path); ins.Log("DIR: ").LogLine(ins.MainModDir); ins.LogLine(e.ToString()); ins.ExeSelected(null); return; } TypeDefinition ModType = ins.MainMod.Module.GetType("ETGMod"); if (ModType != null) { MethodDefinition ModCctor = null; for (int i = 0; i < ModType.Methods.Count; i++) { if (ModType.Methods[i].IsStatic && ModType.Methods[i].IsConstructor) { ModCctor = ModType.Methods[i]; break; } } /* * .method private hidebysig specialname rtspecialname static * void .cctor () cil managed * { * // Method begins at RVA 0x2d6cec * // Code size 184 (0xb8) * .maxstack 3 * * IL_0000: ldc.i4.0 * IL_0001: ldc.i4.1 * IL_0002: ldc.i4.0 * IL_0003: newobj instance void [mscorlib]System.Version::.ctor(int32, int32, int32) * IL_0008: stsfld class [mscorlib]System.Version ETGMod::BaseVersion * IL_000d: ldc.i4.0 * IL_000e: stsfld int32 ETGMod::BaseTravisBuild * IL_0013: ldc.i4.1 * IL_0014: ldstr "debug" * IL_0019: newobj instance void ETGMod/Profile::.ctor(int32, string) * IL_001e: stsfld class ETGMod/Profile ETGMod::BaseProfile */ if (ModCctor != null) { string modVersion = ""; string modBuild = ""; string modProfile = ""; for (int i = 0; i < ModCctor.Body.Instructions.Count; i++) { Instruction instructionField = ModCctor.Body.Instructions[i]; if (instructionField.OpCode != OpCodes.Stsfld) { continue; } FieldReference field = (FieldReference)instructionField.Operand; if (field.Name == "BaseVersion") { int count = ((MethodReference)ModCctor.Body.Instructions[i - 1].Operand).Parameters.Count; for (int ii = i - count - 1; ii < i - 1; ii++) { modVersion += ModCctor.Body.Instructions[ii].GetInt(); if (ii < i - 2) { modVersion += "."; } } } if (field.Name == "BaseTravisBuild") { int build = ModCctor.Body.Instructions[i - 1].GetInt(); if (build != 0) { modBuild = "-" + build; } } if (field.Name == "BaseProfile") { string profile = ModCctor.Body.Instructions[i - 2].Operand as string; if (!string.IsNullOrEmpty(profile)) { modProfile = "-" + profile; } } } ins.ModVersion = modVersion + modBuild + modProfile; } } ins.Invoke(delegate() { ins.ExeStatusLabel.Text = "Enter The Gungeon"; ins.ExeStatusLabel.BackColor = Color.FromArgb(127, 63, 255, 91); if (ins.ModVersion != null) { ins.ExeStatusLabel.Text += " [Mod:"; ins.ExeStatusLabel.Text += ins.ModVersion; ins.ExeStatusLabel.Text += "]"; } if (suffix != null) { ins.ExeStatusLabel.Text += suffix; } ins.ExePathBox.Text = origPath; ins.InstallButton.Enabled = true; ETGInstallerSettings.Save(); OnExeSelected?.Invoke(true); }); }