diff --git a/PalCalc.Model/PalDB.cs b/PalCalc.Model/PalDB.cs index fe39e2e..0146a6d 100644 --- a/PalCalc.Model/PalDB.cs +++ b/PalCalc.Model/PalDB.cs @@ -150,15 +150,11 @@ private class Serialized private static ILogger logger = Log.ForContext(); + private static object loadEmbeddedLock = new object(); private static PalDB embedded = null; - public static PalDB LoadEmbedded() - { - if (embedded != null) - { - logger.Verbose("Using previously-loaded pal DB"); - return embedded; - } + private static PalDB _LoadEmbedded() + { logger.Information("Loading embedded pal DB"); var info = Assembly.GetExecutingAssembly().GetName(); var name = info.Name; @@ -166,11 +162,38 @@ public static PalDB LoadEmbedded() .GetExecutingAssembly() .GetManifestResourceStream($"{name}.db.json")!; + PalDB result; using (var streamReader = new StreamReader(stream, Encoding.UTF8)) - embedded = FromJson(streamReader.ReadToEnd()); + result = FromJson(streamReader.ReadToEnd()); logger.Information("Successfully loaded embedded pal DB"); - return embedded; + return result; + } + + public static void BeginLoadEmbedded() + { + Task.Run(() => + { + lock (loadEmbeddedLock) + { + embedded = _LoadEmbedded(); + } + }); + } + + public static PalDB LoadEmbedded() + { + lock (loadEmbeddedLock) + { + if (embedded != null) + { + logger.Verbose("Using previously-loaded pal DB"); + return embedded; + } + + embedded = _LoadEmbedded(); + return embedded; + } } public static PalDB FromJson(string json) => JsonConvert.DeserializeObject(json); diff --git a/PalCalc.SaveReader/SaveFile/ISaveFile.cs b/PalCalc.SaveReader/SaveFile/ISaveFile.cs index 31ff973..fee4c79 100644 --- a/PalCalc.SaveReader/SaveFile/ISaveFile.cs +++ b/PalCalc.SaveReader/SaveFile/ISaveFile.cs @@ -17,25 +17,9 @@ public ISaveFile(string filePath) public string FilePath { get; } public bool Exists => File.Exists(FilePath); - public bool IsValid - { - get - { - if (!Exists) return false; - if (!CompressedSAV.IsValidSave(FilePath)) return false; - - return GvasFile.IsValidGvas(FilePath); - //var isValidSave = false; - //CompressedSAV.WithDecompressedSave(FilePath, stream => - //{ - // using (var reader = new FArchiveReader(stream, PalWorldTypeHints.Hints)) - // isValidSave = GvasFile.IsValidGvas(reader); - //}); - - //return isValidSave; - } - } + private bool? isValid = null; + public bool IsValid => isValid ??= Exists && GvasFile.IsValidGvas(FilePath); public DateTime LastModified => File.GetLastWriteTime(FilePath); diff --git a/PalCalc.Solver.CLI/Program.cs b/PalCalc.Solver.CLI/Program.cs index 987364a..0be61f1 100644 --- a/PalCalc.Solver.CLI/Program.cs +++ b/PalCalc.Solver.CLI/Program.cs @@ -27,7 +27,8 @@ static void Main(string[] args) ownedPals: savedInstances, maxBreedingSteps: 20, maxWildPals: 1, - maxIrrelevantTraits: 0, + maxBredIrrelevantTraits: 0, + maxInputIrrelevantTraits: 2, maxEffort: TimeSpan.FromDays(7) ); diff --git a/PalCalc.UI/App.xaml.cs b/PalCalc.UI/App.xaml.cs index f6ed3dd..532838a 100644 --- a/PalCalc.UI/App.xaml.cs +++ b/PalCalc.UI/App.xaml.cs @@ -17,7 +17,7 @@ namespace PalCalc.UI /// public partial class App : Application { - public static string Version => "v0.9-BETA"; + public static string Version => "v1.0.0"; private static ILogger logger; @@ -42,6 +42,10 @@ protected override void OnStartup(StartupEventArgs e) .CreateLogger(); logger = Log.ForContext(); + logger.Information($"Pal Calc version {Version}"); + + PalDB.BeginLoadEmbedded(); + base.OnStartup(e); } diff --git a/PalCalc.UI/MainWindow.xaml.cs b/PalCalc.UI/MainWindow.xaml.cs index 97ef964..79d054c 100644 --- a/PalCalc.UI/MainWindow.xaml.cs +++ b/PalCalc.UI/MainWindow.xaml.cs @@ -1,8 +1,10 @@ using PalCalc.UI.View; using PalCalc.UI.ViewModel; +using Serilog; using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -23,10 +25,15 @@ namespace PalCalc.UI /// public partial class MainWindow : Window { + private ILogger logger = Log.ForContext(); + public MainWindow() { InitializeComponent(); + + var sw = Stopwatch.StartNew(); DataContext = new MainWindowViewModel(Dispatcher); + logger.Information("MainWindowViewModel took {ms}ms to start", sw.ElapsedMilliseconds); } private MainWindowViewModel ViewModel => DataContext as MainWindowViewModel; diff --git a/PalCalc.UI/ViewModel/MainWindowViewModel.cs b/PalCalc.UI/ViewModel/MainWindowViewModel.cs index b643876..30e00c2 100644 --- a/PalCalc.UI/ViewModel/MainWindowViewModel.cs +++ b/PalCalc.UI/ViewModel/MainWindowViewModel.cs @@ -146,7 +146,7 @@ public MainWindowViewModel(Dispatcher dispatcher) if (settings.SelectedGameIdentifier != null) SaveSelection.TrySelectSaveGame(settings.SelectedGameIdentifier); - UpdateFromSaveProperties(); + dispatcher.BeginInvoke(UpdateFromSaveProperties, DispatcherPriority.Background); } private void SaveSelection_CustomSaveAdded(ManualSavesLocationViewModel manualSaves, ISaveGame save) diff --git a/PalCalc.UI/ViewModel/Mapped/SaveGameViewModel.cs b/PalCalc.UI/ViewModel/Mapped/SaveGameViewModel.cs index ada5db2..c5ed142 100644 --- a/PalCalc.UI/ViewModel/Mapped/SaveGameViewModel.cs +++ b/PalCalc.UI/ViewModel/Mapped/SaveGameViewModel.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; @@ -37,6 +38,8 @@ public SaveGameViewModel(ISaveGame value) logger.Warning(ex, "error when loading LevelMeta for {saveId}", CachedSaveGame.IdentifierFor(value)); Label = $"{value.GameId} (Unable to read metadata)"; } + + IsValid = Value.IsValid; } public DateTime LastModified => Value.LastModified; @@ -45,7 +48,7 @@ public SaveGameViewModel(ISaveGame value) public CachedSaveGame CachedValue => Storage.LoadSave(Value, PalDB.LoadEmbedded()); public string Label { get; } - public bool IsValid => Value.IsValid; + public bool IsValid { get; } public bool IsAddManualOption { get; } diff --git a/README.md b/README.md index 237b2bf..1f2ae5e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Pal Calc is a Windows program for calculating the optimal steps to breed a speci - Can detect and read from your local game save files, based on [palworld-save-tools by cheahjs](https://github.com/cheahjs/palworld-save-tools) - Supports local Steam saves and Xbox saves - - Xbox saves are synced to your PC by downloading the game through the 'Xbox' app on Windows and running the game at least once. Save files are synced when the game is run. + - Xbox saves are synced to your PC by downloading the game through the ['Xbox' app on Windows](https://apps.microsoft.com/detail/9mv0b5hzvk9z) and running the game at least once. Save files are synced when the game is run. - Provides time estimates on each step, based on probabilities and mechanics [derived by /u/mgxts in this Reddit post](https://www.reddit.com/r/Palworld/comments/1af9in7/passive_skill_inheritance_mechanics_in_breeding/) - Gender probabilities - Probability of directly- and randomly-inserted traits