diff --git a/.vs/RemnantWorldChanger/DesignTimeBuild/.dtbcache.v2 b/.vs/RemnantWorldChanger/DesignTimeBuild/.dtbcache.v2 index d452f77..c53fdc8 100644 Binary files a/.vs/RemnantWorldChanger/DesignTimeBuild/.dtbcache.v2 and b/.vs/RemnantWorldChanger/DesignTimeBuild/.dtbcache.v2 differ diff --git a/.vs/RemnantWorldChanger/FileContentIndex/198bd21a-8c5c-46e5-b9fb-3d4c76cdbdde.vsidx b/.vs/RemnantWorldChanger/FileContentIndex/198bd21a-8c5c-46e5-b9fb-3d4c76cdbdde.vsidx deleted file mode 100644 index cc8df44..0000000 Binary files a/.vs/RemnantWorldChanger/FileContentIndex/198bd21a-8c5c-46e5-b9fb-3d4c76cdbdde.vsidx and /dev/null differ diff --git a/.vs/RemnantWorldChanger/FileContentIndex/9aa8c741-812e-43bb-810f-490e30ab4cfb.vsidx b/.vs/RemnantWorldChanger/FileContentIndex/9aa8c741-812e-43bb-810f-490e30ab4cfb.vsidx new file mode 100644 index 0000000..9123d28 Binary files /dev/null and b/.vs/RemnantWorldChanger/FileContentIndex/9aa8c741-812e-43bb-810f-490e30ab4cfb.vsidx differ diff --git a/.vs/RemnantWorldChanger/FileContentIndex/d8b2ea12-eae8-455e-8309-2000c27e4ffa.vsidx b/.vs/RemnantWorldChanger/FileContentIndex/d8b2ea12-eae8-455e-8309-2000c27e4ffa.vsidx deleted file mode 100644 index 6a44bd0..0000000 Binary files a/.vs/RemnantWorldChanger/FileContentIndex/d8b2ea12-eae8-455e-8309-2000c27e4ffa.vsidx and /dev/null differ diff --git a/.vs/RemnantWorldChanger/FileContentIndex/ed03b120-702a-4f46-83e6-8397d49f1ab8.vsidx b/.vs/RemnantWorldChanger/FileContentIndex/ed03b120-702a-4f46-83e6-8397d49f1ab8.vsidx new file mode 100644 index 0000000..2017df8 Binary files /dev/null and b/.vs/RemnantWorldChanger/FileContentIndex/ed03b120-702a-4f46-83e6-8397d49f1ab8.vsidx differ diff --git a/.vs/RemnantWorldChanger/v17/.suo b/.vs/RemnantWorldChanger/v17/.suo index e7d6fb4..11d341e 100644 Binary files a/.vs/RemnantWorldChanger/v17/.suo and b/.vs/RemnantWorldChanger/v17/.suo differ diff --git a/BulkSave.cs b/BulkSave.cs index 866449d..a5bbb0e 100644 --- a/BulkSave.cs +++ b/BulkSave.cs @@ -13,6 +13,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; +using System.Windows; using static RemnantWorldChanger.DataPackage; namespace RemnantWorldChanger @@ -28,7 +29,7 @@ public static T RandomEnumValue() } public ObservableCollection SaveInfo { get; set; } - private Dictionary GuidToBytes { get; set; } + public Dictionary GuidToBytes { get; set; } public BulkSave(ObservableCollection header, Dictionary data) { @@ -48,7 +49,6 @@ public void AddSave(byte[] savedata, SaveType type = SaveType.All, string world GuidToBytes.Add(guid, savedata); var dp = new DataPackage(guid) { Difficulty = diff, World = world, Name = name, Mods = mods, Type = type }; SaveInfo.Add(dp); - //Debug.WriteLine("Created: "+dp); } public void AddSave(byte[] savedata, DataPackage dp) { @@ -56,6 +56,7 @@ public void AddSave(byte[] savedata, DataPackage dp) SaveInfo.Add(dp); } + public static DirectoryInfo TryGetSolutionDirectoryInfo(string currentPath = null) { var directory = new DirectoryInfo( @@ -67,7 +68,6 @@ public static DirectoryInfo TryGetSolutionDirectoryInfo(string currentPath = nul return directory; } - [Conditional("DEBUG")] public void SerializeData(string name) { if (!Directory.Exists(name)) @@ -86,16 +86,37 @@ public void SerializeData(string name) } public static BulkSave DeserializeData(string path) { - var header = new ObservableCollection(Directory.EnumerateFiles(path, "*.RIndex").Select(s => JsonSerializer.Deserialize>(File.ReadAllText(s))).SelectMany(x => x)); + var indexes = Directory.EnumerateFiles(path, "*.RIndex"); + if (indexes.Count() > 1) + MessageBox.Show("Multiple Data Files detected!"); + + ObservableCollection header = new ObservableCollection(); + Dictionary bulk = new Dictionary(); + + foreach (string index in indexes) + { + var data = Path.ChangeExtension(index, ".RData"); + if (!File.Exists(data)) + { + MessageBox.Show($"{Path.GetFileName(data)} does not exist!!"); + continue; + } + header = new ObservableCollection(header.Union(JsonSerializer.Deserialize>(File.ReadAllText(index)))); + + JsonSerializer.Deserialize>(File.ReadAllText(data)).ToList().ForEach(pair => bulk[pair.Key] = pair.Value); - var data = Directory.EnumerateFiles(path, "*.RData").Select(s => JsonSerializer.Deserialize>(File.ReadAllText(s))).SelectMany(x => x).ToDictionary(x => x.Key, y => y.Value); + } - return new BulkSave(header, data); + //var header = new ObservableCollection(Directory.EnumerateFiles(path, "*.RIndex").Select(s => JsonSerializer.Deserialize>(File.ReadAllText(s))).SelectMany(x => x).GroupBy(x=>x.ID).Select(x=>x.First())); + + // var data = Directory.EnumerateFiles(path, "*.RData").Select(s => JsonSerializer.Deserialize>(File.ReadAllText(s))).SelectMany(x => x).GroupBy(kvp=>kvp.Key).ToDictionary(kvp => kvp.Key, kvp => kvp.First().Value); + + return new BulkSave(header, bulk); } } - public class DataPackage + public class DataPackage : IEquatable { public enum SaveDifficulty { Unset, Survivor, Veteran, Nightmare, Apocalypse } public enum SaveType { All, MiniBoss, WorldBoss, SideD, OverworldPOI, Vendor } @@ -123,6 +144,15 @@ public DataPackage(Guid guid, SaveType type = SaveType.All, SaveDifficulty diff { return $"Type: {Type.ToString()} World: {World} Name: {Name} Difficulty: {Difficulty.ToString()} Mods: {Mods} GUID: {ID}"; } + + public bool Equals(DataPackage? other) + { + if (other is null) + return false; + return this.Difficulty == other.Difficulty && this.Name == other.Name && this.Mods == other.Mods; + } + public override bool Equals(object obj) => Equals(obj as DataPackage); + public override int GetHashCode() => (Difficulty, Name, Mods).GetHashCode(); } } diff --git a/DictionaryExtensions.cs b/DictionaryExtensions.cs new file mode 100644 index 0000000..b286cd0 --- /dev/null +++ b/DictionaryExtensions.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Text.Json; +using System.Threading.Tasks; +using System.Windows; +using System.Runtime.Intrinsics.Arm; +using System.Diagnostics; + +namespace RemnantWorldChanger +{ + public static class DictionaryExtensions + { + public static bool ChangeKey(this IDictionary dict, + TKey oldKey, TKey newKey) + { + if (!dict.Remove(oldKey, out var value)) + return false; + + dict[newKey] = value; // or dict.Add(newKey, value) depending on ur comfort + return true; + } + public static bool NewPackage(this BulkSave Saves, out DataPackage dp) + { + Guid guid = Guid.NewGuid(); + return EditPackage(Saves, dp = new DataPackage(guid), false); + } + public static bool EditPackage(this BulkSave Saves, DataPackage dp, bool editmode = true) + { + SaveEditor editor = new SaveEditor(dp); + + if (editor.ShowDialog() == false) + { + Debug.WriteLine("Dialog Result False"); + return false; + } + + if (editor.Save is null) + { + Debug.WriteLine("Editor Save Null"); + return false; + } + + + if (editmode && dp.ID != editor.Save.ID) + { + var _ = MessageBox.Show($"Warning GUID Mismatch:\n\nOld: {dp.ID}\nNew: {editor.Save.ID}\n\nChange GUID?", "GUID Mismatch", MessageBoxButton.YesNoCancel); + if (_ == MessageBoxResult.Cancel) + return false; + + if (_ == MessageBoxResult.No) + editor.Save.ID = dp.ID; + else + { + Saves.GuidToBytes.ChangeKey(dp.ID, editor.Save.ID); + } + } + + if ((editmode == Saves.SaveInfo.Remove(dp))) + Saves.SaveInfo.Add(editor.Save); + else + return false; + return true; + + + } + } +} diff --git a/MainWindow.xaml b/MainWindow.xaml index 303891e..62c9fc0 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -13,8 +13,9 @@ - - + + + @@ -32,6 +33,7 @@ + @@ -48,6 +50,7 @@ + @@ -63,6 +66,7 @@ + diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 86940e5..9c97525 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1,6 +1,7 @@ using Microsoft.Win32; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.Eventing.Reader; using System.IO; @@ -99,6 +100,8 @@ private void EnableDebugOptions() btnGenExample.IsEnabled = true; } + + private void SaveCheckpoint_Click(object sender, RoutedEventArgs e) { Debug.WriteLine("Saving Checkpoint....."); @@ -110,8 +113,12 @@ private void SaveCheckpoint_Click(object sender, RoutedEventArgs e) DataPackage? dp; if (ofd.ShowDialog() == true) - if ((dp = NewPackage()) is not null) - Saves.AddSave(File.ReadAllBytes(ofd.FileName), dp); + if (Saves.NewPackage(out dp)) + Saves.GuidToBytes.Add(dp.ID, File.ReadAllBytes(ofd.FileName)); + else + Debug.WriteLine("New Package Failed!"); + else + Debug.WriteLine("Dialog False"); SaveList.SelectedIndex = 0; ViewUpdate(); @@ -208,48 +215,15 @@ public bool Exists(string name, SaveDifficulty diff, string mod, out DataPackage return true; } - private DataPackage? NewPackage() - { - Guid guid = Guid.NewGuid(); - return EditPackage(new DataPackage(guid)); - } - private DataPackage? EditPackage(DataPackage dp) - { - SaveEditor editor = new SaveEditor() { }; - var ser = new JsonSerializerOptions - { - WriteIndented = true - }; - ser.Converters.Add(new JsonStringEnumConverter()); - editor.EditorWindow.Text = JsonSerializer.Serialize(dp, ser); - - if (editor.ShowDialog() == false) - return null; - - if (editor.Save is null) - return null; - - return editor.Save; - - - } private void SaveEdit_Click(object sender, RoutedEventArgs e) { var dp = FindSelected(); if (dp != null) { Debug.WriteLine($"FOUND: {dp} GUID:{dp.ID}"); - DataPackage? dpo; - if ((dpo = EditPackage(dp)) is not null) - if (Saves.SaveInfo.Remove(dp)) - Saves.SaveInfo.Add(dpo); - SaveList.ItemsSource = Saves.SaveInfo.GroupBy(x => x.Name).ToDictionary(x => x.Key, x => x.First().World); - DifficultyList.ItemsSource = Saves.SaveInfo.Select(x => x.Difficulty).Distinct(); - ModifierList.ItemsSource = Saves.SaveInfo.Select(x => x.Mods).Distinct(); - - ViewUpdate(); - + if (Saves.EditPackage(dp)) + ViewUpdate(); } else { Debug.WriteLine($"Editor: False"); } } @@ -284,8 +258,20 @@ private void Save_SelectionChanged(object sender, SelectionChangedEventArgs e) private void LoadSave_Click(object sender, RoutedEventArgs e) { - Debug.WriteLine($"Loading: {FindSelected()}"); + DataPackage? _ = FindSelected(); + Debug.WriteLine($"Loading: {_}"); + if (_ is null) + return; + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Filter = "World Saves (.sav)|save_*.sav"; + ofd.DefaultExt = ".sav"; + ofd.Title = "Overwrite Save"; + + if (ofd.ShowDialog() == true) + File.WriteAllBytes(ofd.FileName, Saves.GuidToBytes[_.ID]); + else + Debug.WriteLine("Load Save Failed!"); } private void CheckBox_Checked(object sender, RoutedEventArgs e) @@ -351,5 +337,29 @@ private void LockedSave_Changed(object sender, FileSystemEventArgs e) }); SaveWatcher.EnableRaisingEvents = true; } + + private void ViewDataFolder_Click(object sender, RoutedEventArgs e) + { + try + { + Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Packages); + } + catch (Win32Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void DeleteSave_Click(object sender, RoutedEventArgs e) + { + var _ = FindSelected(); + if (_ == null) + return; + var result = MessageBox.Show($"Are you sure you want to delete: \n\nDifficulty: {_.Difficulty}\nName: {_.Name}\nMods: {_.Mods} ", "WARNING", MessageBoxButton.YesNo, MessageBoxImage.Warning); + if (result == MessageBoxResult.Yes) + if (Saves.GuidToBytes.Remove(_.ID)) + Saves.SaveInfo.Remove(_); + ViewUpdate(); + } } } diff --git a/Properties/PublishProfiles/FolderProfile.pubxml b/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..87cc0b7 --- /dev/null +++ b/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,17 @@ + + + + + Release + Any CPU + bin\Release\ + FileSystem + <_TargetId>Folder + net6.0-windows + false + win-x64 + false + + \ No newline at end of file diff --git a/Properties/PublishProfiles/FolderProfile.pubxml.user b/Properties/PublishProfiles/FolderProfile.pubxml.user new file mode 100644 index 0000000..86853f2 --- /dev/null +++ b/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -0,0 +1,10 @@ + + + + + True|2023-08-21T18:59:25.2633679Z;True|2023-08-21T12:01:47.2938761-04:00;False|2023-08-21T12:01:22.4718346-04:00;True|2023-08-21T12:00:32.1813074-04:00; + + + \ No newline at end of file diff --git a/RemnantWorldChanger.csproj b/RemnantWorldChanger.csproj index ecd69e9..f58fcf4 100644 --- a/RemnantWorldChanger.csproj +++ b/RemnantWorldChanger.csproj @@ -1,25 +1,35 @@  - - WinExe - net6.0-windows - enable - true - + + WinExe + net6.0-windows + true + true + enable + true + - - - True - True - Settings.settings - - + + embedded + - - - SettingsSingleFileGenerator - Settings.Designer.cs - - + + embedded + + + + + True + True + Settings.settings + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + diff --git a/RemnantWorldChanger.csproj.user b/RemnantWorldChanger.csproj.user index 9dc2643..a10eb4b 100644 --- a/RemnantWorldChanger.csproj.user +++ b/RemnantWorldChanger.csproj.user @@ -1,6 +1,8 @@  - + + <_LastSelectedProfileId>C:\Users\Josh\Documents\GitHub\RemnantWorldChanger\Properties\PublishProfiles\FolderProfile.pubxml + Designer diff --git a/SaveEditor.xaml b/SaveEditor.xaml index 30a1336..5980be0 100644 --- a/SaveEditor.xaml +++ b/SaveEditor.xaml @@ -5,10 +5,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:RemnantWorldChanger" mc:Ignorable="d" - Title="SaveEditor" Height="450" Width="450"> - - - + Title="SaveEditor" Height="325" Width="475" MinHeight="325" MinWidth="500"> + + +