From 621a3067fe98fbcdb9e58e3bc9d6e6b1b0f008e5 Mon Sep 17 00:00:00 2001 From: Asval Date: Tue, 6 Aug 2019 12:38:07 +0200 Subject: [PATCH] added toolstrip to download my backups + fixed QuestBundle_S9_Fortbyte_LoadingScreen --- FModel/FModel.csproj | 1 + FModel/Forms/Settings.Designer.cs | 6 +-- FModel/Forms/Settings.cs | 4 +- FModel/MainWindow.Designer.cs | 46 +++++++++++++------ FModel/MainWindow.cs | 45 ++++++++++++++++++ FModel/MainWindow.resx | 2 +- .../ChallengeGenerator/BundleDesign.cs | 4 +- .../ChallengeGenerator/BundleInfos.cs | 18 ++++++-- .../ChallengeGenerator/ChallengeInfoEntry.cs | 4 -- FModel/Methods/PakHelper/BackupFilesEntry.cs | 20 ++++++++ FModel/Methods/PakHelper/CreateBackup.cs | 35 +++++++++++++- FModel/Methods/PakHelper/PakHelper.cs | 6 ++- README.md | 1 + 13 files changed, 160 insertions(+), 32 deletions(-) create mode 100644 FModel/Methods/PakHelper/BackupFilesEntry.cs diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 5f9fa025..c054a04f 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -159,6 +159,7 @@ + diff --git a/FModel/Forms/Settings.Designer.cs b/FModel/Forms/Settings.Designer.cs index 4e7936a6..db836746 100644 --- a/FModel/Forms/Settings.Designer.cs +++ b/FModel/Forms/Settings.Designer.cs @@ -428,11 +428,11 @@ namespace FModel.Forms // this.label7.AutoSize = true; this.label7.ForeColor = System.Drawing.Color.Red; - this.label7.Location = new System.Drawing.Point(89, 113); + this.label7.Location = new System.Drawing.Point(106, 113); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(117, 13); + this.label7.Size = new System.Drawing.Size(86, 13); this.label7.TabIndex = 33; - this.label7.Text = "Banner Size: 1024x256"; + this.label7.Text = "4:1 Aspect Ratio"; // // button4 // diff --git a/FModel/Forms/Settings.cs b/FModel/Forms/Settings.cs index b3f59854..1c8be9e4 100644 --- a/FModel/Forms/Settings.cs +++ b/FModel/Forms/Settings.cs @@ -34,7 +34,7 @@ namespace FModel.Forms textBox6.Text = Properties.Settings.Default.challengesWatermark; if (string.IsNullOrWhiteSpace(textBox6.Text)) { - textBox6.Text = "{Bundle_Name} Generated using FModel & JohnWickParse - {Date}"; + textBox6.Text = "@UseTheWatermarkBecauseWhyNot - {Date}"; } else { textBox6.Text = Properties.Settings.Default.challengesWatermark; } @@ -291,7 +291,7 @@ namespace FModel.Forms newForm.Size = pictureBox1.Image.Size; newForm.Icon = Resources.FModel; - newForm.Text = ThePak.CurrentUsedItem; + newForm.Text = "Challenges Design Template"; newForm.StartPosition = FormStartPosition.CenterScreen; newForm.Controls.Add(pb); newForm.Show(); diff --git a/FModel/MainWindow.Designer.cs b/FModel/MainWindow.Designer.cs index 44f7c4f6..8ca9fc73 100644 --- a/FModel/MainWindow.Designer.cs +++ b/FModel/MainWindow.Designer.cs @@ -48,6 +48,7 @@ namespace FModel this.searchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); this.saveAsJSONToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.autoSaveAsJSONToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); this.copySelectedFilePathToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); @@ -88,7 +89,8 @@ namespace FModel this.saveAsJSONToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); this.extractFolderContentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.autoSaveAsJSONToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); + this.downloadBackupsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.statusStrip1.SuspendLayout(); this.menuStrip1.SuspendLayout(); this.panel1.SuspendLayout(); @@ -155,7 +157,9 @@ namespace FModel this.loadOneToolStripMenuItem, this.loadAllToolStripMenuItem, this.toolStripSeparator1, + this.downloadBackupsToolStripMenuItem, this.backupPAKsToolStripMenuItem, + this.toolStripSeparator8, this.differenceModeToolStripMenuItem, this.updateModeToolStripMenuItem, this.toolStripSeparator2, @@ -167,26 +171,26 @@ namespace FModel // loadOneToolStripMenuItem // this.loadOneToolStripMenuItem.Name = "loadOneToolStripMenuItem"; - this.loadOneToolStripMenuItem.Size = new System.Drawing.Size(162, 22); + this.loadOneToolStripMenuItem.Size = new System.Drawing.Size(220, 22); this.loadOneToolStripMenuItem.Text = "Load One PAK"; this.loadOneToolStripMenuItem.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.loadOneToolStripMenuItem_DropDownItemClicked); // // loadAllToolStripMenuItem // this.loadAllToolStripMenuItem.Name = "loadAllToolStripMenuItem"; - this.loadAllToolStripMenuItem.Size = new System.Drawing.Size(162, 22); + this.loadAllToolStripMenuItem.Size = new System.Drawing.Size(220, 22); this.loadAllToolStripMenuItem.Text = "Load All PAKs"; this.loadAllToolStripMenuItem.Click += new System.EventHandler(this.loadAllToolStripMenuItem_Click); // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(159, 6); + this.toolStripSeparator1.Size = new System.Drawing.Size(217, 6); // // backupPAKsToolStripMenuItem // this.backupPAKsToolStripMenuItem.Name = "backupPAKsToolStripMenuItem"; - this.backupPAKsToolStripMenuItem.Size = new System.Drawing.Size(162, 22); + this.backupPAKsToolStripMenuItem.Size = new System.Drawing.Size(220, 22); this.backupPAKsToolStripMenuItem.Text = "Backup PAKs"; this.backupPAKsToolStripMenuItem.Click += new System.EventHandler(this.backupPAKsToolStripMenuItem_Click); // @@ -194,7 +198,7 @@ namespace FModel // this.differenceModeToolStripMenuItem.CheckOnClick = true; this.differenceModeToolStripMenuItem.Name = "differenceModeToolStripMenuItem"; - this.differenceModeToolStripMenuItem.Size = new System.Drawing.Size(162, 22); + this.differenceModeToolStripMenuItem.Size = new System.Drawing.Size(220, 22); this.differenceModeToolStripMenuItem.Text = "Difference Mode"; this.differenceModeToolStripMenuItem.CheckedChanged += new System.EventHandler(this.differenceModeToolStripMenuItem_CheckedChanged); // @@ -203,21 +207,21 @@ namespace FModel this.updateModeToolStripMenuItem.CheckOnClick = true; this.updateModeToolStripMenuItem.Enabled = false; this.updateModeToolStripMenuItem.Name = "updateModeToolStripMenuItem"; - this.updateModeToolStripMenuItem.Size = new System.Drawing.Size(162, 22); + this.updateModeToolStripMenuItem.Size = new System.Drawing.Size(220, 22); this.updateModeToolStripMenuItem.Text = "Update Mode"; this.updateModeToolStripMenuItem.CheckedChanged += new System.EventHandler(this.updateModeToolStripMenuItem_CheckedChanged); // // toolStripSeparator2 // this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(159, 6); + this.toolStripSeparator2.Size = new System.Drawing.Size(217, 6); // // settingsToolStripMenuItem // this.settingsToolStripMenuItem.Image = global::FModel.Properties.Resources.properties_16xLG; this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; this.settingsToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F1; - this.settingsToolStripMenuItem.Size = new System.Drawing.Size(162, 22); + this.settingsToolStripMenuItem.Size = new System.Drawing.Size(220, 22); this.settingsToolStripMenuItem.Text = "Settings"; this.settingsToolStripMenuItem.Click += new System.EventHandler(this.settingsToolStripMenuItem_Click); // @@ -257,6 +261,13 @@ namespace FModel this.saveAsJSONToolStripMenuItem.Text = "Save as JSON"; this.saveAsJSONToolStripMenuItem.Click += new System.EventHandler(this.SaveAsJSONToolStripMenuItem_Click); // + // autoSaveAsJSONToolStripMenuItem + // + this.autoSaveAsJSONToolStripMenuItem.CheckOnClick = true; + this.autoSaveAsJSONToolStripMenuItem.Name = "autoSaveAsJSONToolStripMenuItem"; + this.autoSaveAsJSONToolStripMenuItem.Size = new System.Drawing.Size(197, 22); + this.autoSaveAsJSONToolStripMenuItem.Text = "Auto Save as JSON"; + // // toolStripSeparator5 // this.toolStripSeparator5.Name = "toolStripSeparator5"; @@ -621,12 +632,17 @@ namespace FModel this.extractFolderContentsToolStripMenuItem.Text = "Extract Folder Contents"; this.extractFolderContentsToolStripMenuItem.Click += new System.EventHandler(this.ExtractFolderContentsToolStripMenuItem_Click); // - // autoSaveAsJSONToolStripMenuItem + // toolStripSeparator8 // - this.autoSaveAsJSONToolStripMenuItem.CheckOnClick = true; - this.autoSaveAsJSONToolStripMenuItem.Name = "autoSaveAsJSONToolStripMenuItem"; - this.autoSaveAsJSONToolStripMenuItem.Size = new System.Drawing.Size(197, 22); - this.autoSaveAsJSONToolStripMenuItem.Text = "Auto Save as JSON"; + this.toolStripSeparator8.Name = "toolStripSeparator8"; + this.toolStripSeparator8.Size = new System.Drawing.Size(217, 6); + // + // downloadBackupsToolStripMenuItem + // + this.downloadBackupsToolStripMenuItem.Name = "downloadBackupsToolStripMenuItem"; + this.downloadBackupsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.downloadBackupsToolStripMenuItem.Text = "Download Backups"; + this.downloadBackupsToolStripMenuItem.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.DownloadBackupsToolStripMenuItem_DropDownItemClicked); // // MainWindow // @@ -722,6 +738,8 @@ namespace FModel private System.Windows.Forms.ToolStripMenuItem openExtractionFolderToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; private System.Windows.Forms.ToolStripMenuItem autoSaveAsJSONToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator8; + private System.Windows.Forms.ToolStripMenuItem downloadBackupsToolStripMenuItem; } } diff --git a/FModel/MainWindow.cs b/FModel/MainWindow.cs index f613520d..819cbed8 100644 --- a/FModel/MainWindow.cs +++ b/FModel/MainWindow.cs @@ -17,6 +17,7 @@ using FModel.Forms; using FModel.Properties; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using RestSharp; using Image = System.Drawing.Image; using Settings = FModel.Properties.Settings; @@ -102,6 +103,19 @@ namespace FModel loadOneToolStripMenuItem.DropDownItems.Add(thePak); })); } + private void AddBackupFiles() + { + if (CreateBackup.backupFilesList != null && CreateBackup.backupFilesList.Count > 0) + { + foreach (var item in CreateBackup.backupFilesList) + { + Invoke(new Action(() => + { + downloadBackupsToolStripMenuItem.DropDownItems.Add(item.bFileName); + })); + } + } + } /// /// check if path exists @@ -169,6 +183,8 @@ namespace FModel FillWithPaKs(); AddToUI.checkAndAddDynamicKeys(); Utilities.colorMyPaks(loadOneToolStripMenuItem); + CreateBackup.GetFilesFromDropbox(); + AddBackupFiles(); Utilities.SetFolderPermission(App.DefaultOutputPath); Utilities.CreateDefaultFolders(); }); @@ -538,6 +554,35 @@ namespace FModel CreateBackup.CreateBackupList(); }); } + private async void DownloadBackupsToolStripMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) + { + await Task.Run(() => { + if (CreateBackup.backupFilesList != null && CreateBackup.backupFilesList.Count > 0) + { + string filename = CreateBackup.backupFilesList.Where(x => string.Equals(x.bFileName, e.ClickedItem.Text)).Select(x => x.bFileName).FirstOrDefault(); + string downloadLink = CreateBackup.backupFilesList.Where(x => string.Equals(x.bFileName, e.ClickedItem.Text)).Select(x => x.bFileDownload).FirstOrDefault(); + if (!string.IsNullOrEmpty(downloadLink)) + { + new UpdateMyState("Downloading " + filename, "Waiting").ChangeProcessState(); + + RestClient EndpointClient = new RestClient(downloadLink); + RestRequest EndpointRequest = new RestRequest(Method.GET); + string content = EndpointClient.Execute(EndpointRequest).Content; + + File.WriteAllText(App.DefaultOutputPath + "\\Backup\\" + filename, content); + if (new System.IO.FileInfo(App.DefaultOutputPath + "\\Backup\\" + filename).Length > 0) + { + new UpdateMyState("\\Backup\\" + filename + " successfully downloaded", "Success").ChangeProcessState(); + } + else + { + File.Delete(App.DefaultOutputPath + "\\Backup\\" + filename); + new UpdateMyState("Can't download " + filename, "Error").ChangeProcessState(); + } + } + } + }); + } //UPDATE MODE private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) diff --git a/FModel/MainWindow.resx b/FModel/MainWindow.resx index 1e2e95b8..c08c9df4 100644 --- a/FModel/MainWindow.resx +++ b/FModel/MainWindow.resx @@ -131,7 +131,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABa - CAAAAk1TRnQBSQFMAgEBAgEAAfABAQHwAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CAAAAk1TRnQBSQFMAgEBAgEAAfgBAQH4AQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/FModel/Methods/IconGenerator/ChallengeGenerator/BundleDesign.cs b/FModel/Methods/IconGenerator/ChallengeGenerator/BundleDesign.cs index 4f27b004..9037debc 100644 --- a/FModel/Methods/IconGenerator/ChallengeGenerator/BundleDesign.cs +++ b/FModel/Methods/IconGenerator/ChallengeGenerator/BundleDesign.cs @@ -227,7 +227,9 @@ namespace FModel JToken bundleCompletionRewards = myBundle["BundleCompletionRewards"]; if (bundleCompletionRewards != null) { + new UpdateMyState("Drawing Completion Rewards...", "Waiting").ChangeProcessState(); theY += 35; + JArray bundleCompletionRewardsArray = bundleCompletionRewards.Value(); foreach (JToken token in bundleCompletionRewardsArray) { @@ -267,7 +269,7 @@ namespace FModel { string rewardId = Path.GetFileName(assetPathName.Value().Substring(0, assetPathName.Value().LastIndexOf(".", StringComparison.Ordinal))); - if (!assetPathName.Value().Contains("/Game/Items/Tokens/") && !rewardId.Contains("Quest_BR_")) //no fortbyte for weekly challenges + if (!assetPathName.Value().Contains("/Game/Items/Tokens/") && !rewardId.Contains("Quest_BR_")) //no more fortbyte for weekly challenges { theY += 90; drawCompletionText(myBitmap, compCount); diff --git a/FModel/Methods/IconGenerator/ChallengeGenerator/BundleInfos.cs b/FModel/Methods/IconGenerator/ChallengeGenerator/BundleInfos.cs index 6d3dd2e3..bb646e6f 100644 --- a/FModel/Methods/IconGenerator/ChallengeGenerator/BundleInfos.cs +++ b/FModel/Methods/IconGenerator/ChallengeGenerator/BundleInfos.cs @@ -181,14 +181,24 @@ namespace FModel JToken description = token["Description"]; if (description != null) { - descriptionKey = description["key"].Value(); - descriptionSource = description["source_string"].Value(); + JToken key = description["key"]; + JToken sourceString = description["source_string"]; + if (key != null && sourceString != null) + { + descriptionKey = key.Value(); + descriptionSource = sourceString.Value(); + } } JToken descriptionMain = AssetArray[0]["Description"]; if (descriptionMain != null) { - descriptionKey = descriptionMain["key"].Value(); - descriptionSource = descriptionMain["source_string"].Value(); + JToken key = descriptionMain["key"]; + JToken sourceString = descriptionMain["source_string"]; + if (key != null && sourceString != null) + { + descriptionKey = key.Value(); + descriptionSource = sourceString.Value(); + } } } diff --git a/FModel/Methods/IconGenerator/ChallengeGenerator/ChallengeInfoEntry.cs b/FModel/Methods/IconGenerator/ChallengeGenerator/ChallengeInfoEntry.cs index 24d20350..3e8be47d 100644 --- a/FModel/Methods/IconGenerator/ChallengeGenerator/ChallengeInfoEntry.cs +++ b/FModel/Methods/IconGenerator/ChallengeGenerator/ChallengeInfoEntry.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace FModel { diff --git a/FModel/Methods/PakHelper/BackupFilesEntry.cs b/FModel/Methods/PakHelper/BackupFilesEntry.cs new file mode 100644 index 00000000..f164c12b --- /dev/null +++ b/FModel/Methods/PakHelper/BackupFilesEntry.cs @@ -0,0 +1,20 @@ +using System; + +namespace FModel +{ + public struct BackupFilesEntry : IEquatable + { + internal BackupFilesEntry(string fileName, string fileDownload) + { + bFileName = fileName; + bFileDownload = fileDownload; + } + public string bFileName { get; set; } + public string bFileDownload { get; set; } + + bool IEquatable.Equals(BackupFilesEntry other) + { + throw new NotImplementedException(); + } + } +} diff --git a/FModel/Methods/PakHelper/CreateBackup.cs b/FModel/Methods/PakHelper/CreateBackup.cs index 1509548f..f30e6975 100644 --- a/FModel/Methods/PakHelper/CreateBackup.cs +++ b/FModel/Methods/PakHelper/CreateBackup.cs @@ -1,6 +1,8 @@ using csharp_wick; using FModel.Properties; +using Newtonsoft.Json.Linq; using System; +using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; @@ -10,6 +12,8 @@ namespace FModel { static class CreateBackup { + public static List backupFilesList { get; set; } + public static void CreateBackupList() { PakExtractor extractor = null; @@ -79,7 +83,7 @@ namespace FModel } File.WriteAllText(App.DefaultOutputPath + "\\Backup" + Checking.BackupFileName, sb.ToString()); //File will always exist so we check the file size instead - if (new System.IO.FileInfo(App.DefaultOutputPath + "\\Backup" + Checking.BackupFileName).Length > 0) + if (new FileInfo(App.DefaultOutputPath + "\\Backup" + Checking.BackupFileName).Length > 0) { new UpdateMyState("\\Backup" + Checking.BackupFileName + " successfully created", "Success").ChangeProcessState(); } @@ -89,5 +93,34 @@ namespace FModel new UpdateMyState("Can't create " + Checking.BackupFileName.Substring(1), "Error").ChangeProcessState(); } } + + public static void GetFilesFromDropbox() + { + try + { + if (DLLImport.IsInternetAvailable()) + { + string backupFiles = Keychain.GetEndpoint("https://dl.dropbox.com/s/lngkoq2ucd9di2n/FModel_Backups.json?dl=0"); + backupFilesList = new List(); + + if (!string.IsNullOrEmpty(backupFiles)) + { + JArray array = JArray.Parse(backupFiles); + foreach (JProperty prop in array.Children().Properties()) + { + backupFilesList.Add(new BackupFilesEntry(prop.Name, prop.Value.Value())); + } + } + } + else + { + new UpdateMyConsole("Your internet connection is currently unavailable, can't check for backup files at the moment.", Color.Red, true).AppendToConsole(); + } + } + catch (Exception) + { + new UpdateMyConsole("[FModel] Error while checking for backup files", Color.Red, true).AppendToConsole(); + } + } } } diff --git a/FModel/Methods/PakHelper/PakHelper.cs b/FModel/Methods/PakHelper/PakHelper.cs index 5b0429da..c40e0e45 100644 --- a/FModel/Methods/PakHelper/PakHelper.cs +++ b/FModel/Methods/PakHelper/PakHelper.cs @@ -70,9 +70,11 @@ namespace FModel { theExtractor = new PakExtractor(Settings.Default.PAKsPath + "\\" + pakName, pakKey); } - catch (Exception) + catch (Exception ex) { - new UpdateMyConsole("0x" + pakKey + " doesn't work with " + ThePak.dynamicPaksList[i].thePak, Color.Red, true).AppendToConsole(); + if (string.Equals(ex.Message, "Extraction failed")) { new UpdateMyConsole("0x" + pakKey + " doesn't work with " + ThePak.dynamicPaksList[i].thePak, Color.Red, true).AppendToConsole(); } + else { new UpdateMyConsole("Message: " + ex.Message + "\nSource: " + ex.Source + "\nTarget: " + ex.TargetSite, Color.Red, true).AppendToConsole(); } + if (theExtractor != null) { theExtractor.Dispose(); } continue; } diff --git a/README.md b/README.md index 461fe62b..baddb21b 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ Also if you find this project useful, feel free to give it a :star: thank you :k - [ScintillaNET](https://www.nuget.org/packages/jacobslusser.ScintillaNET) - [Find & Replace for ScintillaNET](https://www.nuget.org/packages/snt.ScintillaNet.FindReplaceDialog/) - [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) + - [Cyotek ColorPicker](https://github.com/cyotek/Cyotek.Windows.Forms.ColorPicker) ### Contributors
Waddlesworth
Waddlesworth

🔧
Maiky M
Maiky M

🔧🐦
AyeTSG
AyeTSG

🔧🐦
FireMonkey
FireMonkey

🔧🐦