diff --git a/BlueprintExplorer/BlueprintDB.cs b/BlueprintExplorer/BlueprintDB.cs index 66db881..1184e15 100644 --- a/BlueprintExplorer/BlueprintDB.cs +++ b/BlueprintExplorer/BlueprintDB.cs @@ -450,6 +450,9 @@ public void ExtractFromGame(ConnectionProgress progress, string wrathPath, strin .FirstOrDefault(); var typeIdGuid = typeIdType.GetField("GuidString"); + if (typeIdGuid == null) { + typeIdGuid = typeIdType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).First(f => f.Name.Contains("GuidString", StringComparison.InvariantCultureIgnoreCase)); + } foreach (var type in types) { @@ -591,7 +594,15 @@ public bool TryConnect(ConnectionProgress progress, string forceFileName = null) header.Major = headerIn.ReadInt32(); header.Minor = headerIn.ReadInt32(); header.Patch = headerIn.ReadInt32(); - header.Suffix = headerIn.ReadChar(); + try + { + header.Suffix = headerIn.ReadString(); + } // binz files created in the old BubblePrints version will only have char here. + catch (EndOfStreamException) { + headerIn.BaseStream.Position = 0; + for (int i = 0; i < 3; i++) headerIn.ReadInt32(); + header.Suffix = headerIn.ReadChar().ToString(); + } header.Bubble = 0; count = headerIn.ReadInt32(); diff --git a/BlueprintExplorer/BubblePrints.cs b/BlueprintExplorer/BubblePrints.cs index 1947164..cb84095 100644 --- a/BlueprintExplorer/BubblePrints.cs +++ b/BlueprintExplorer/BubblePrints.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; @@ -62,13 +62,13 @@ public static void Install() } } - private static Regex ExtractVersionPattern = new(@"(?\d)\.(?\d)\.(?\d+)(?[a-zA-Z]?)"); + private static Regex ExtractVersionPattern = new(@"(?\d+)\.(?\d+)\.(?\d+)(?\.\d+|[a-zA-Z]*)"); internal static GameVersion GetGameVersion(string wrathPath) { if (Game_Data == "Kingmaker_Data") { - return new(2, 1, 4, 'a', 0); + return new(2, 1, 4, "a", 0); } var versionPath = Path.Combine(wrathPath, Game_Data, "StreamingAssets", "Version.info"); @@ -99,13 +99,18 @@ internal static GameVersion GetGameVersion(string wrathPath) var major = int.Parse(r.Groups["major"].Value); var minor = int.Parse(r.Groups["minor"].Value); var patch = int.Parse(r.Groups["patch"].Value); - char.TryParse(r.Groups["suffix"].Value, out char suffix); + var suffix = r.Groups["suffix"].Value; return new(major, minor, patch, suffix, 0); } internal static void SetWrathPath(bool forceSelect) { - var path = Settings.WrathPath; + var path = BubblePrints.Game_Data switch { + "Wrath_Data" => Settings.WrathPath, + "Kingmaker_Data" => Settings.KMPath, + "WH40KRT_Data" => Settings.RTPath, + _ => throw new NotSupportedException() + }; if (forceSelect) { path = null; @@ -147,7 +152,12 @@ static bool ContainsDirectory(string path, string directoryName) => } if (!errored) { - Settings.WrathPath = path; + switch (BubblePrints.Game_Data) { + case "Wrath_Data": Settings.WrathPath = path; break; + case "Kingmaker_Data": Settings.KMPath = path; break; + case "WH40KRT_Data": Settings.RTPath = path; break; + default: throw new NotSupportedException(); + }; SaveSettings(); } } @@ -169,7 +179,7 @@ static bool ContainsDirectory(string path, string directoryName) => public static string CurrentGame => Game_Data switch { - "Kingmaker_Data" => "Kingmaker", + "Kingmaker_Data" => "KM", "Wrath_Data" => "Wrath", "WH40KRT_Data" => "RT", _ => throw new NotSupportedException(), @@ -257,6 +267,16 @@ public SettingsProxy(SettingsProxy settings) [Editor(typeof(FileNameEditor), typeof(UITypeEditor))] public string WrathPath { get; set; } + [Description("Full path to your Kingmaker folder (i.e. the folder containing Kingmaker.exe")] + [DisplayName("Kingmaker Install Folder")] + [Editor(typeof(FileNameEditor), typeof(UITypeEditor))] + public string KMPath { get; set; } + + [Description("Full path to your Rogue Trader folder (i.e. the folder containing WH40KRT.exe")] + [DisplayName("Rogue Trader Install Folder")] + [Editor(typeof(FileNameEditor), typeof(UITypeEditor))] + public string RTPath { get; set; } + [Description("If set, clicking on a blueprint in the search results will automatically open it in the external editor")] [DisplayName("Always Open Externally")] public bool AlwaysOpenInEditor { get; set; } diff --git a/BlueprintExplorer/GameVersion.cs b/BlueprintExplorer/GameVersion.cs index 912f66d..67a3a48 100644 --- a/BlueprintExplorer/GameVersion.cs +++ b/BlueprintExplorer/GameVersion.cs @@ -6,10 +6,10 @@ public partial class BlueprintDB { public struct GameVersion : IComparable { public int Major, Minor, Patch; - public char Suffix; + public string Suffix; public int Bubble; - public GameVersion(int major, int minor, int patch, char suffix, int bubble) + public GameVersion(int major, int minor, int patch, string suffix, int bubble) { Major = major; Minor = minor; @@ -39,8 +39,13 @@ public int CompareTo(GameVersion other) public override int GetHashCode() => HashCode.Combine(Major, Minor, Patch, Suffix, Bubble); - public override string ToString() => $"{Major}.{Minor}.{Patch}{(Suffix == default ? "" : Suffix.ToString())}_{Bubble}"; - + public override string ToString() { + if (int.TryParse(Suffix, out var _)) { + return $"{Major}.{Minor}.{Patch}.{Suffix}_{Bubble}"; + } else { + return $"{Major}.{Minor}.{Patch}{(Suffix == default ? "" : Suffix)}_{Bubble}"; + } + } } } } diff --git a/BlueprintExplorer/SplashScreenChooserJobbie.cs b/BlueprintExplorer/SplashScreenChooserJobbie.cs index f5dbe2d..5d34d0f 100644 --- a/BlueprintExplorer/SplashScreenChooserJobbie.cs +++ b/BlueprintExplorer/SplashScreenChooserJobbie.cs @@ -23,13 +23,14 @@ namespace BlueprintExplorer public partial class SplashScreenChooserJobbie : Form { private readonly BindingList Available = new(); + private List PreSort; private readonly Dictionary ByVersion = new(); public SplashScreenChooserJobbie() { InitializeComponent(); loadAnim = new(); - + PreSort = new(); try { if (!Directory.Exists(CacheDir)) @@ -37,39 +38,18 @@ public SplashScreenChooserJobbie() Console.WriteLine("setting available = from web"); using var web = new WebClient(); + ParseWebJson(web, "https://raw.githubusercontent.com/factubsio/BubblePrintsData/main/versions.json", "Wrath"); + ParseWebJson(web, "https://raw.githubusercontent.com/factubsio/BubblePrintsData/main/versions_RT.json", "RT"); + ParseWebJson(web, "https://raw.githubusercontent.com/factubsio/BubblePrintsData/main/versions_KM.json", "KM"); + - var raw = web.DownloadString("https://raw.githubusercontent.com/factubsio/BubblePrintsData/main/versions.json"); - var versions = JsonSerializer.Deserialize(raw); - foreach (var version in versions.EnumerateArray()) - { - GameVersion gv = new() - { - Major = version[0].GetInt32(), - Minor = version[1].GetInt32(), - Patch = version[2].GetInt32(), - Suffix = version[3].GetString()[0], - Bubble = version[4].GetInt32(), - }; - Binz binz = new() - { - Version = new() - { - Version = gv, - Game = "Wrath", - }, - Source = "bubbles", - }; - Available.Insert(0, binz); - ByVersion.Add(binz.Version, binz); - } } catch (Exception ex) { Console.Error.WriteLine(ex.Message); } - foreach (var file in Directory.EnumerateFiles(BubblePrints.DataPath, "*.binz")) { BinzVersion v = VersionFromFile(file); @@ -87,11 +67,16 @@ public SplashScreenChooserJobbie() Version = v, Source = "local", }; - Available.Insert(0, binz); + PreSort.Insert(0, binz); ByVersion.Add(v, binz); } } - + PreSort.Sort((a, b) => { + var tmp = b.Version.Game.CompareTo(a.Version.Game); + if (tmp == 0) return a.Version.Version.CompareTo(b.Version.Version); + else return tmp; + }); + PreSort.ForEach(i => Available.Insert(0, i)); versions.SelectionChanged += OnSelectedRowChanged; versions.SelectionMode = DataGridViewSelectionMode.FullRowSelect; @@ -114,6 +99,29 @@ public SplashScreenChooserJobbie() } } } + public void ParseWebJson(WebClient web, string url, string game) { + var raw = web.DownloadString(url); + var versions = JsonSerializer.Deserialize(raw); + + foreach (var version in versions.EnumerateArray()) { + GameVersion gv = new() { + Major = version[0].GetInt32(), + Minor = version[1].GetInt32(), + Patch = version[2].GetInt32(), + Suffix = version[3].GetString(), + Bubble = version[4].GetInt32(), + }; + Binz binz = new() { + Version = new() { + Version = gv, + Game = game, + }, + Source = "bubbles", + }; + PreSort.Insert(0, binz); + ByVersion.Add(binz.Version, binz); + } + } private void OnSelectedRowChanged(object sender, EventArgs e) { @@ -125,21 +133,21 @@ private void OnSelectedRowChanged(object sender, EventArgs e) delete.Enabled = selected.Local; } - private static Regex extractVersion = new(@"blueprints_raw_(\d+).(\d+)\.(\d+)(.)_(\d).binz"); - private static Regex extractVersionKM = new(@"blueprints_raw_km_(\d+).(\d+)\.(\d+)(.)_(\d).binz"); - private static Regex extractVersionRT = new(@"blueprints_raw_RT_(\d+).(\d+)\.(\d+)(.)_(\d).binz"); + private static Regex extractVersion = new(@"blueprints_raw_(\d+).(\d+)\.(\d+)(.*)_(\d).binz"); + private static Regex extractVersionKM = new(@"blueprints_raw_KM_(\d+).(\d+)\.(\d+)(.)_(\d).binz"); + private static Regex extractVersionRT = new(@"blueprints_raw_RT_(\d+).(\d+)\.(\d+)(\.\d+|.*)_(\d).binz"); private static BinzVersion VersionFromFile(string file) { Match match; string game = "Wrath"; string fileName = Path.GetFileName(file); - if (fileName.StartsWith("blueprints_raw_km")) + if (fileName.StartsWith("blueprints_raw_KM", StringComparison.InvariantCultureIgnoreCase)) { match = extractVersionKM.Match(file); - game = "Kingmaker"; + game = "KM"; } - else if (fileName.StartsWith("blueprints_raw_RT")) + else if (fileName.StartsWith("blueprints_raw_RT", StringComparison.InvariantCultureIgnoreCase)) { match = extractVersionRT.Match(file); game = "RT"; @@ -154,7 +162,7 @@ private static BinzVersion VersionFromFile(string file) Major = int.Parse(match.Groups[1].Value), Minor = int.Parse(match.Groups[2].Value), Patch = int.Parse(match.Groups[3].Value), - Suffix = match.Groups[4].Value[0], + Suffix = match.Groups[4].Value, Bubble = int.Parse(match.Groups[5].Value), }; return new() @@ -219,16 +227,16 @@ private async void DoLoadSelected(object sender, EventArgs e) BubblePrints.Game_Data = toLoad.Version.Game switch { "Wrath" => "Wrath_Data", - "Kingmaker" => "Kingmaker_Data", + "KM" => "Kingmaker_Data", "RT" => "WH40KRT_Data", _ => throw new NotSupportedException(), }; if (!toLoad.Local) { - if (toLoad.Version.Game != "Wrath") + if (toLoad.Version.Game != "KM" && toLoad.Version.Game != "Wrath" && toLoad.Version.Game != "RT") { - throw new Exception("Can only auto-download wrath binz"); + throw new Exception("Can only auto-download km, wrath and rt binz"); } loadAnim.Image = Resources.downloading; @@ -236,8 +244,10 @@ private async void DoLoadSelected(object sender, EventArgs e) loadAnim.Caption = "Downloading"; const string host = "https://github.com/factubsio/BubblePrintsData/releases/download"; string filename = BlueprintDB.FileNameFor(toLoad.Version.Version, toLoad.Version.Game); - var latestVersionUrl = new Uri($"{host}/{toLoad.Version.Version}/{filename}"); - + Uri latestVersionUrl = null; + if (toLoad.Version.Game == "Wrath") latestVersionUrl = new Uri($"{host}/{toLoad.Version.Version}/{filename}"); + else if (toLoad.Version.Game == "RT") latestVersionUrl = new Uri($"{host}/RT_{toLoad.Version.Version}/{filename}"); + else if (toLoad.Version.Game == "KM") latestVersionUrl = new Uri($"{host}/KM_{toLoad.Version.Version}/{filename}"); var client = new WebClient(); string tmp = Path.Combine(CacheDir, "binz_download.tmp"); @@ -249,6 +259,7 @@ private async void DoLoadSelected(object sender, EventArgs e) client.DownloadProgressChanged += (sender, e) => loadAnim.SetPercentSafe(e.ProgressPercentage); var download = client.DownloadFileTaskAsync(latestVersionUrl, tmp); await download; + if (File.Exists(toLoad.Path)) File.Delete(toLoad.Path); File.Move(tmp, toLoad.Path); }