From d4ea2254e6ec61c3e1aa22afd92cfebf0e8c7281 Mon Sep 17 00:00:00 2001
From: Andrew Savinykh <658865+AndrewSav@users.noreply.github.com>
Date: Mon, 6 May 2024 13:41:18 +1200
Subject: [PATCH] add more debug logging, fixed a few typos
---
CHANGELOG.md | 10 +-
Remnant2SaveAnalyzer/App.config | 9 +
Remnant2SaveAnalyzer/Logger.cs | 218 +++++-----
.../Properties/Settings.Designer.cs | 36 ++
.../Properties/Settings.settings | 9 +
.../Remnant2SaveAnalyzer.csproj | 2 +-
Remnant2SaveAnalyzer/RemnantSave.cs | 407 ++++++++++--------
.../Views/Pages/SettingsPage.xaml | 27 ++
.../Views/Pages/WorldAnalyzerPage.xaml.cs | 2 +-
.../locales/Strings.Designer.cs | 45 ++
Remnant2SaveAnalyzer/locales/Strings.resx | 15 +
11 files changed, 493 insertions(+), 287 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89397e6..4600693 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,14 @@
# Changelog
-
-## 0.0.4 (unreleased)
+## 0.0.5 (unreleased)
- Add ability to hide already looted items for those item, where it can be detected - work in progress
- Add ability to hide items unobtainable in the current run without reroll - work in progress
-- Add more debug logging - work in progress
-- Fixed a few typos
+## 0.0.4 (6 May 2024)
+- Add option to log save data for debugging purposes
+- Add option to dump analyzer data structures in json for debugging purposes
+- Add option to log performance metrics for debugging purposes
+- Fixed a few typos
## 0.0.3 (3 May 2024)
diff --git a/Remnant2SaveAnalyzer/App.config b/Remnant2SaveAnalyzer/App.config
index 8b3d984..91d2e29 100644
--- a/Remnant2SaveAnalyzer/App.config
+++ b/Remnant2SaveAnalyzer/App.config
@@ -178,6 +178,15 @@
True
+
+ False
+
+
+ False
+
+
+ False
+
\ No newline at end of file
diff --git a/Remnant2SaveAnalyzer/Logger.cs b/Remnant2SaveAnalyzer/Logger.cs
index d8306bd..47e1754 100644
--- a/Remnant2SaveAnalyzer/Logger.cs
+++ b/Remnant2SaveAnalyzer/Logger.cs
@@ -1,111 +1,111 @@
-using Remnant2SaveAnalyzer.Views.Windows;
-using System;
-using System.Collections.Generic;
-using System.IO;
-
-namespace Remnant2SaveAnalyzer
-{
- internal static class Logger
- {
- public static event EventHandler? MessageLogged;
-
- static Logger()
- {
- if (Properties.Settings.Default.CreateLogFile)
- {
- CreateLog();
- }
- Properties.Settings.Default.PropertyChanged += Default_PropertyChanged;
- }
-
- public static List Messages { get; } = [];
-
- private static void Default_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
- {
- if (e.PropertyName != "CreateLogFile")
- {
- return;
- }
- if (!Properties.Settings.Default.CreateLogFile)
- {
- return;
- }
- CreateLog();
- }
-
- private static void CreateLog()
- {
- File.WriteAllText("log.txt", DateTime.Now + ": Version " + typeof(MainWindow).Assembly.GetName().Version + "\r\n");
- }
-
- public static void Log(object? message, LogType logType, bool silent = false)
- {
- message ??= "null";
- if (!silent)
- {
- MessageLogged?.Invoke(null, new(message.ToString() ?? "", logType));
- }
- Messages.Add(new(message.ToString() ?? "", logType));
- if (Properties.Settings.Default.CreateLogFile)
- {
- StreamWriter writer = File.AppendText("log.txt");
- writer.WriteLine($"{DateTime.Now}[{logType}]: {message}");
- writer.Close();
- }
- //Debug.WriteLine(message);
- }
-
- public static void Log(object message)
- {
- Log(message, LogType.Normal);
+using Remnant2SaveAnalyzer.Views.Windows;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Remnant2SaveAnalyzer
+{
+ internal static class Logger
+ {
+ public static event EventHandler? MessageLogged;
+
+ static Logger()
+ {
+ if (Properties.Settings.Default.CreateLogFile)
+ {
+ CreateLog();
+ }
+ Properties.Settings.Default.PropertyChanged += Default_PropertyChanged;
+ }
+
+ public static List Messages { get; } = [];
+
+ private static void Default_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName != "CreateLogFile")
+ {
+ return;
+ }
+ if (!Properties.Settings.Default.CreateLogFile)
+ {
+ return;
+ }
+ CreateLog();
}
- public static void LogSilent(object message)
- {
- Log(message, LogType.Normal, true);
- }
-
- public static void Success(object message)
- {
- Log(message, LogType.Success);
- }
-
- public static void Error(object message)
- {
- Log(message, LogType.Error);
- }
-
- public static void Warn(object message)
- {
- Log(message, LogType.Warning);
- }
-
- public static void WarnSilent(string message)
- {
- Log(message, LogType.Warning, true);
- }
- }
-
- public enum LogType
- {
- Normal,
- Success,
- Error,
- Warning,
- }
-
- public class MessageLoggedEventArgs(string message, LogType logType) : EventArgs
- {
- public string Message { get; set; } = message;
- public LogType LogType { get; set;} = logType;
-
- public MessageLoggedEventArgs(string message) : this(message, LogType.Normal)
- {
- }
- }
- public class LogMessage(string message, LogType logType)
- {
- public string Message { get; set; } = message;
- public LogType LogType { get; set; } = logType;
- }
-}
+ private static void CreateLog()
+ {
+ File.WriteAllText("log.txt", DateTime.Now + ": Version " + typeof(MainWindow).Assembly.GetName().Version + "\r\n");
+ }
+
+ public static void Log(object? message, LogType logType, bool silent = false)
+ {
+ message ??= "null";
+ if (!silent)
+ {
+ MessageLogged?.Invoke(null, new(message.ToString() ?? "", logType));
+ }
+ Messages.Add(new(message.ToString() ?? "", logType));
+ if (Properties.Settings.Default.CreateLogFile)
+ {
+ StreamWriter writer = File.AppendText("log.txt");
+ writer.WriteLine($"{DateTime.Now} [{logType}]: {message}");
+ writer.Close();
+ }
+ //Debug.WriteLine(message);
+ }
+
+ public static void Log(object message)
+ {
+ Log(message, LogType.Normal);
+ }
+
+ public static void LogSilent(object message)
+ {
+ Log(message, LogType.Normal, true);
+ }
+
+ public static void Success(object message)
+ {
+ Log(message, LogType.Success);
+ }
+
+ public static void Error(object message)
+ {
+ Log(message, LogType.Error);
+ }
+
+ public static void Warn(object message)
+ {
+ Log(message, LogType.Warning);
+ }
+
+ public static void WarnSilent(string message)
+ {
+ Log(message, LogType.Warning, true);
+ }
+ }
+
+ public enum LogType
+ {
+ Normal,
+ Success,
+ Error,
+ Warning,
+ }
+
+ public class MessageLoggedEventArgs(string message, LogType logType) : EventArgs
+ {
+ public string Message { get; set; } = message;
+ public LogType LogType { get; set;} = logType;
+
+ public MessageLoggedEventArgs(string message) : this(message, LogType.Normal)
+ {
+ }
+ }
+ public class LogMessage(string message, LogType logType)
+ {
+ public string Message { get; set; } = message;
+ public LogType LogType { get; set; } = logType;
+ }
+}
diff --git a/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs b/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs
index 8c43c38..c462194 100644
--- a/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs
+++ b/Remnant2SaveAnalyzer/Properties/Settings.Designer.cs
@@ -706,5 +706,41 @@ public bool ShowItemsWithNoPrerequisites {
this["ShowItemsWithNoPrerequisites"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool ReportPerformance {
+ get {
+ return ((bool)(this["ReportPerformance"]));
+ }
+ set {
+ this["ReportPerformance"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool ReportPlayerInfo {
+ get {
+ return ((bool)(this["ReportPlayerInfo"]));
+ }
+ set {
+ this["ReportPlayerInfo"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool DumpAnalyzerJson {
+ get {
+ return ((bool)(this["DumpAnalyzerJson"]));
+ }
+ set {
+ this["DumpAnalyzerJson"] = value;
+ }
+ }
}
}
diff --git a/Remnant2SaveAnalyzer/Properties/Settings.settings b/Remnant2SaveAnalyzer/Properties/Settings.settings
index 9358f4d..da60127 100644
--- a/Remnant2SaveAnalyzer/Properties/Settings.settings
+++ b/Remnant2SaveAnalyzer/Properties/Settings.settings
@@ -173,5 +173,14 @@
True
+
+ False
+
+
+ False
+
+
+ False
+
\ No newline at end of file
diff --git a/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj b/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj
index a41cb70..a10c585 100644
--- a/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj
+++ b/Remnant2SaveAnalyzer/Remnant2SaveAnalyzer.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/Remnant2SaveAnalyzer/RemnantSave.cs b/Remnant2SaveAnalyzer/RemnantSave.cs
index b7533d7..9f22682 100644
--- a/Remnant2SaveAnalyzer/RemnantSave.cs
+++ b/Remnant2SaveAnalyzer/RemnantSave.cs
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using lib.remnant2.analyzer.Model;
using lib.remnant2.analyzer;
using Newtonsoft.Json;
-using Wpf.Ui.Controls;
+using Remnant2SaveAnalyzer.Properties;
namespace Remnant2SaveAnalyzer
{
@@ -97,195 +98,257 @@ public void UpdateCharacters()
bool first = _remnantDataset == null;
_remnantDataset = Analyzer.Analyze(_savePath, _remnantDataset);
- if (first && _remnantDataset.DebugMessages.Count > 0)
+ if (first)
{
- Logger.WarnSilent("BEGIN Analyser warnings");
- foreach (string message in _remnantDataset.DebugMessages)
+ ReportAnalyzerDebugMessages();
+ if (Settings.Default.ReportPerformance)
+ {
+ ReportAnalyzerPerformanceMetrics();
+ }
+
+ if (Settings.Default.ReportPlayerInfo)
{
- Logger.WarnSilent(message);
+ ReportPlayerInfo();
}
- Logger.Warn("There were some analyzer warnings");
+ if (Settings.Default.DumpAnalyzerJson)
+ {
+ DumpAnalyzerJson();
+ }
}
- /*
- if (_remnantDataset.DebugPerformance.Count > 0)
+ }
+ }
+
+ private void ReportAnalyzerDebugMessages()
+ {
+ if (_remnantDataset is { DebugMessages.Count: > 0 })
+ {
+ Logger.WarnSilent("BEGIN Analyser warnings");
+ foreach (string message in _remnantDataset.DebugMessages)
+ {
+ Logger.WarnSilent(" " + message);
+ }
+ Logger.Warn("There were some analyzer warnings");
+ }
+ }
+
+ private void ReportAnalyzerPerformanceMetrics()
+ {
+ if (_remnantDataset is { DebugPerformance.Count: > 0 })
+ {
+ Logger.LogSilent("BEGIN Performance metrics");
+ foreach (KeyValuePair message in _remnantDataset.DebugPerformance)
+ {
+ Logger.LogSilent($" {message.Key}; {message.Value}");
+ }
+ Logger.LogSilent("END Performance metrics");
+ }
+ }
+
+ private void DumpAnalyzerJson()
+ {
+ JsonSerializer serializer = new()
+ {
+ Formatting = Formatting.Indented,
+ ContractResolver = new Exporter.IgnorePropertiesResolver([
+ "Dataset",
+ "Parent",
+ "ProfileSaveFile",
+ "ProfileNavigator",
+ "WorldSaveFile",
+ "WorldNavigator",
+ "Character"
+ ]),
+ NullValueHandling = NullValueHandling.Ignore
+ };
+
+ using StreamWriter sw = new(@"analyzer.json");
+ using JsonWriter writer = new JsonTextWriter(sw);
+ serializer.Serialize(writer, _remnantDataset);
+ }
+
+ private void ReportPlayerInfo()
+ {
+ Debug.Assert(_remnantDataset != null, nameof(_remnantDataset) + " != null");
+ Logger.LogSilent($"Active character save: save_{_remnantDataset.ActiveCharacterIndex}.sav");
+
+ // Account Awards ------------------------------------------------------------
+ Logger.LogSilent("BEGIN Account Awards");
+ foreach (string award in _remnantDataset.AccountAwards)
+ {
+ if (award.StartsWith("AccountAward_"))
{
- Logger.WarnSilent("BEGIN Performance metrics");
- foreach (KeyValuePair message in _remnantDataset.DebugPerformance)
+ LootItem? lootItem = ItemDb.GetItemByIdOrDefault(award);
+ if (lootItem == null)
+ {
+ Logger.WarnSilent($" UnknownMarker account award: {award}");
+ }
+ else
{
- Logger.WarnSilent($"{message.Key}; {message.Value}");
+ Logger.LogSilent($" Account award: {lootItem.Name}");
}
- Logger.WarnSilent("END Performance metrics");
}
- */
- if (first)
+ }
+ foreach (Dictionary m in ItemDb.Db.Where(x => x["Type"] == "award" && !_remnantDataset.AccountAwards.Exists(y => y == x["Id"])))
+ {
+ Logger.LogSilent($" Missing {Utils.Capitalize(m["Type"])}: {m["Name"]}");
+ }
+ Logger.LogSilent("END Account Awards");
+
+ for (int index = 0; index < _remnantDataset.Characters.Count; index++)
+ {
+ // Character ------------------------------------------------------------
+ var character = _remnantDataset.Characters[index];
+ int acquired = character.Profile.AcquiredItems;
+ int missing = character.Profile.MissingItems.Count;
+ int total = acquired + missing;
+ Logger.LogSilent($"Character {index+1} (save_{character.Index}), Acquired Items: {acquired}, Missing Items: {missing}, Total: {total}");
+ Logger.LogSilent($"Is Hardcore: {character.Profile.IsHardcore}");
+ Logger.LogSilent($"Trait Rank: {character.Profile.TraitRank}");
+ Logger.LogSilent($"Last Saved Trait Points: {character.Profile.LastSavedTraitPoints}");
+ Logger.LogSilent($"Power Level: {character.Profile.PowerLevel}");
+ Logger.LogSilent($"Item Level: {character.Profile.ItemLevel}");
+ Logger.LogSilent($"Gender: {character.Profile.Gender}");
+
+ // Inventory ------------------------------------------------------------
+ Logger.LogSilent($"BEGIN Inventory, Character {index+1} (save_{character.Index}), mode: inventory");
+
+ IEnumerable lootItems = character.Profile.Inventory
+ .Select(ItemDb.GetItemByProfileId)
+ .Where(x => x != null)!;
+
+ IEnumerable absent = character.Profile.Inventory.Where(x => ItemDb.GetItemByProfileId(x) == null);
+ foreach (string s in absent)
+ {
+ if (!Utils.IsKnownInventoryItem(Utils.GetNameFromProfileId(s)))
+ {
+
+ Logger.WarnSilent($" Inventory item not found in database: {s}");
+ }
+ }
+
+ List> itemTypes = [.. lootItems
+ .GroupBy(x => x.Type)
+ .OrderBy(x=> x.Key)];
+
+ foreach (IGrouping type in itemTypes)
{
- Logger.LogSilent($"Active character save: save_{_remnantDataset.ActiveCharacterIndex}.sav");
+ Logger.LogSilent(" " + Utils.Capitalize(type.Key)+":");
+ if (!type.Any())
+ {
+ Logger.LogSilent(" None");
+ }
+ foreach (LootItem lootItem in type.OrderBy(x => x.Name))
+ {
+ Logger.LogSilent(" " + lootItem.Name);
+ }
+ }
+
+ Logger.LogSilent($"END Inventory, Character {index+1} (save_{character.Index}), mode: inventory");
+
+
+ // Campaign ------------------------------------------------------------
+ Logger.LogSilent($"Save play time: {Utils.FormatPlaytime(character.Save.Playtime)}");
+ foreach (Zone z in character.Save.Campaign.Zones)
+ {
+ Logger.LogSilent($"Campaign story: {z.Story}");
+ }
+ Logger.LogSilent($"Campaign difficulty: {character.Save.Campaign.Difficulty}");
+ Logger.LogSilent($"Campaign play time: {Utils.FormatPlaytime(character.Save.Campaign.Playtime)}");
+
+ // Campaign Quest Inventory ------------------------------------------------------------
+ Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign");
+ lootItems = character.Save.Campaign.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!;
+ absent = character.Save.Campaign.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null);
+ foreach (string s in absent)
+ {
+ Logger.WarnSilent($" Quest item not found in database: {s}");
+ }
+
+ foreach (LootItem lootItem in lootItems)
+ {
+ Logger.LogSilent(" " + lootItem.Name);
+ }
+ Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign");
+
+ if (character.Save.Adventure != null)
+ {
+ // Adventure ------------------------------------------------------------
+ Logger.LogSilent($"Adventure story: {character.Save.Adventure.Zones[0].Story}");
+ Logger.LogSilent($"Adventure difficulty: {character.Save.Adventure.Difficulty}");
+ Logger.LogSilent($"Adventure play time: {Utils.FormatPlaytime(character.Save.Adventure.Playtime)}");
+
+ // Adventure Quest Inventory ------------------------------------------------------------
+ Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure");
+ lootItems = character.Save.Adventure.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!;
+ absent = character.Save.Adventure.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null);
+ foreach (string s in absent)
+ {
+ Logger.WarnSilent($" Quest item not found in database: {s}");
+ }
- foreach (string award in _remnantDataset.AccountAwards)
+ foreach (LootItem lootItem in lootItems)
{
- if (award.StartsWith("AccountAward_"))
- {
- LootItem? lootItem = ItemDb.GetItemByIdOrDefault(award);
- if (lootItem == null)
- {
- Logger.WarnSilent($"UnknownMarker account award: {award}");
- }
- else
- {
- Logger.LogSilent($"Account award: {lootItem.Name}");
- }
- }
+ Logger.LogSilent(" " + lootItem.Name);
}
- for (int index = 0; index < _remnantDataset.Characters.Count; index++)
+ Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure");
+ }
+
+ // Cass shop ------------------------------------------------------------
+ Logger.LogSilent($"BEGIN Cass shop, Character {index+1} (save_{character.Index})");
+ foreach (LootItem lootItem in character.Save.CassShop)
+ {
+ Logger.LogSilent(" " + lootItem.Name);
+ }
+ Logger.LogSilent($"END Cass shop, Character {index+1} (save_{character.Index})");
+
+ // Quest log ------------------------------------------------------------
+ Logger.LogSilent($"BEGIN Quest log, Character {index+1} (save_{character.Index})");
+ lootItems = character.Save.QuestCompletedLog
+ .Select(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}")).Where(x => x != null)!;
+ absent = character.Save.QuestCompletedLog.Where(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}") == null);
+ foreach (string s in absent)
+ {
+ Logger.WarnSilent($" Quest not found in database: {s}");
+ }
+ foreach (LootItem lootItem in lootItems)
+ {
+ Logger.LogSilent($" {lootItem.Name} ({lootItem.Item["Subtype"]})");
+ }
+ Logger.LogSilent($"END Quest log, Character {index+1} (save_{character.Index})");
+
+ // Achievements ------------------------------------------------------------
+ Logger.LogSilent($"BEGIN Achievements for Character {index+1} (save_{character.Index})");
+ foreach (ObjectiveProgress objective in character.Profile.Objectives)
+ {
+ if (objective.Type == "achievement")
{
- var character = _remnantDataset.Characters[index];
- int acquired = character.Profile.AcquiredItems;
- int missing = character.Profile.MissingItems.Count;
- int total = acquired + missing;
- Logger.LogSilent($"Character {index+1} (save_{character.Index}), Acquired Items: {acquired}, Missing Items: {missing}, Total: {total}");
- Logger.LogSilent($"Is Hardcore: {character.Profile.IsHardcore}");
- Logger.LogSilent($"Trait Rank: {character.Profile.TraitRank}");
- Logger.LogSilent($"Last Saved Trait Points: {character.Profile.LastSavedTraitPoints}");
- Logger.LogSilent($"Power Level: {character.Profile.PowerLevel}");
- Logger.LogSilent($"Item Level: {character.Profile.ItemLevel}");
- Logger.LogSilent($"Gender: {character.Profile.Gender}");
- Logger.LogSilent($"BEGIN Inventory, Character {index+1} (save_{character.Index}), mode: inventory");
-
- IEnumerable lootItems = character.Profile.Inventory
- .Select(ItemDb.GetItemByProfileId)
- .Where(x => x != null)!;
-;
-
- IEnumerable absent = character.Profile.Inventory.Where(x => ItemDb.GetItemByProfileId(x) == null);
- foreach (string s in absent)
- {
- //Logger.WarnSilent($"Inventory item not found in database: {s}");
- }
-
- List> itemTypes = [.. lootItems
- .GroupBy(x => x.Type)
- .OrderBy(x=> x.Key)];
-
- foreach (IGrouping type in itemTypes)
- {
- Logger.LogSilent(Utils.Capitalize(type.Key)+":");
- if (!type.Any())
- {
- Logger.LogSilent(" None");
- }
- foreach (LootItem lootItem in type.OrderBy(x => x.Name))
- {
- Logger.LogSilent(" " + lootItem.Name);
- }
- }
-
- Logger.LogSilent($"END Inventory, Character {index+1} (save_{character.Index}), mode: inventory");
-
- Logger.LogSilent($"Save play time: {Utils.FormatPlaytime(character.Save.Playtime)}");
- foreach (Zone z in character.Save.Campaign.Zones)
- {
- Logger.LogSilent($"Campaign story: {z.Story}");
- }
- Logger.LogSilent($"Campaign difficulty: {character.Save.Campaign.Difficulty}");
- Logger.LogSilent($"Campaign play time: {Utils.FormatPlaytime(character.Save.Campaign.Playtime)}");
- Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign");
- lootItems = character.Save.Campaign.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!;
- absent = character.Save.Campaign.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null);
- foreach (string s in absent)
- {
- Logger.WarnSilent($"Quest item not found in database: {s}");
- }
-
- foreach (LootItem lootItem in lootItems)
- {
- Logger.LogSilent(lootItem.Name);
- }
- Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: campaign");
-
- if (character.Save.Adventure != null)
- {
- Logger.LogSilent($"Adventure story: {character.Save.Adventure.Zones[0].Story}");
- Logger.LogSilent($"Adventure difficulty: {character.Save.Adventure.Difficulty}");
- Logger.LogSilent($"Adventure play time: {Utils.FormatPlaytime(character.Save.Adventure.Playtime)}");
- Logger.LogSilent($"BEGIN Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure");
- lootItems = character.Save.Adventure.QuestInventory.Select(ItemDb.GetItemByProfileId).Where(x => x != null).OrderBy(x => x!.Name)!;
- absent = character.Save.Adventure.QuestInventory.Where(x => ItemDb.GetItemByProfileId(x) == null);
- foreach (string s in absent)
- {
- Logger.WarnSilent($"Quest item not found in database: {s}");
- }
-
- foreach (LootItem lootItem in lootItems)
- {
- Logger.LogSilent(lootItem.Name);
- }
-
- Logger.LogSilent($"END Quest inventory, Character {index+1} (save_{character.Index}), mode: adventure");
- }
-
- Logger.LogSilent($"BEGIN Cass shop, Character {index+1} (save_{character.Index})");
- foreach (LootItem lootItem in character.Save.CassShop)
- {
- Logger.LogSilent(lootItem.Name);
- }
- Logger.LogSilent($"END Cass shop, Character {index+1} (save_{character.Index})");
-
- Logger.LogSilent($"BEGIN Quest log, Character {index+1} (save_{character.Index})");
- lootItems = character.Save.QuestCompletedLog
- .Select(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}")).Where(x => x != null)!;
- absent = character.Save.QuestCompletedLog.Where(x => ItemDb.GetItemByIdOrDefault($"Quest_{x}") == null);
- foreach (string s in absent)
- {
- Logger.WarnSilent($"Quest not found in database: {s}");
- }
- foreach (LootItem lootItem in lootItems)
- {
- Logger.LogSilent($"{lootItem.Name} ({lootItem.Item["Subtype"]})");
- }
- Logger.LogSilent($"END Quest log, Character {index+1} (save_{character.Index})");
-
- Logger.LogSilent($"BEGIN Achievements for Character {index+1} (save_{character.Index})");
- foreach (ObjectiveProgress objective in character.Profile.Objectives)
- {
- if (objective.Type == "achievement")
- {
- Logger.LogSilent($"{Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}");
- }
- }
- Logger.LogSilent($"END Achievements for Character {index+1} (save_{character.Index})");
- Logger.LogSilent($"BEGIN Challenges for Character {index+1} (save_{character.Index})");
- foreach (ObjectiveProgress objective in character.Profile.Objectives)
- {
- if (objective.Type == "challenge")
- {
- Logger.LogSilent($"{Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}");
- }
- }
- Logger.LogSilent($"END Challenges for Character {index+1} (save_{character.Index})");
+ Logger.LogSilent($" {Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}");
}
- /*
- JsonSerializer serializer = new()
+ }
+
+ foreach (Dictionary m in ItemDb.Db.Where(x => x["Type"] == "achievement" && !character.Profile.Objectives.Exists(y => y.Id == x["Id"])))
+ {
+ Logger.LogSilent($" Missing {Utils.Capitalize(m["Type"])}: {m["Name"]}");
+ }
+
+ Logger.LogSilent($"END Achievements for Character {index+1} (save_{character.Index})");
+
+ // Challenges ------------------------------------------------------------
+ Logger.LogSilent($"BEGIN Challenges for Character {index+1} (save_{character.Index})");
+ foreach (ObjectiveProgress objective in character.Profile.Objectives)
+ {
+ if (objective.Type == "challenge")
{
- Formatting = Formatting.Indented,
- ContractResolver = new Analyzer.IgnorePropertiesResolver([
- "Dataset",
- "Parent",
- "ProfileSaveFile",
- "ProfileNavigator",
- "WorldSaveFile",
- "WorldNavigator",
- "Character"
- ]),
- NullValueHandling = NullValueHandling.Ignore
- };
-
- using StreamWriter sw = new(@"d:\test.json");
- using JsonWriter writer = new JsonTextWriter(sw);
- serializer.Serialize(writer, _remnantDataset);
- */
+ Logger.LogSilent($" {Utils.Capitalize(objective.Type)}: {objective.Description} - {objective.Progress}");
+ }
+ }
+ foreach (Dictionary m in ItemDb.Db.Where(x => x["Type"] == "challenge" && !character.Profile.Objectives.Exists(y => y.Id == x["Id"])))
+ {
+ Logger.LogSilent($" Missing {Utils.Capitalize(m["Type"])}: {m["Name"]}");
}
+ Logger.LogSilent($"END Challenges for Character {index+1} (save_{character.Index})");
}
}
diff --git a/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml b/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml
index d0a93ed..ea8a9e9 100644
--- a/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml
+++ b/Remnant2SaveAnalyzer/Views/Pages/SettingsPage.xaml
@@ -275,6 +275,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs b/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs
index 512f109..18141cf 100644
--- a/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs
+++ b/Remnant2SaveAnalyzer/Views/Pages/WorldAnalyzerPage.xaml.cs
@@ -188,7 +188,7 @@ private void SavePlaintextButton_Click(object sender, RoutedEventArgs e)
Logger.Error(Loc.T("export_save_invalid_folder_error"));
return;
}
- Analyzer.Export(openFolderDialog.SelectedPath, _save.SaveFolderPath, Properties.Settings.Default.ExportCopy, Properties.Settings.Default.ExportDecoded, Properties.Settings.Default.ExportJson);
+ Exporter.Export(openFolderDialog.SelectedPath, _save.SaveFolderPath, Properties.Settings.Default.ExportCopy, Properties.Settings.Default.ExportDecoded, Properties.Settings.Default.ExportJson);
Logger.Success(Loc.T($"Exported save files successfully to {openFolderDialog.SelectedPath}"));
} catch (Exception ex)
{
diff --git a/Remnant2SaveAnalyzer/locales/Strings.Designer.cs b/Remnant2SaveAnalyzer/locales/Strings.Designer.cs
index 1231648..4ecdbad 100644
--- a/Remnant2SaveAnalyzer/locales/Strings.Designer.cs
+++ b/Remnant2SaveAnalyzer/locales/Strings.Designer.cs
@@ -294,6 +294,15 @@ public static string chkCreateLogFile_ToolTip {
}
}
+ ///
+ /// Looks up a localized string similar to Dump Analyzer data structures to analyzer.json .
+ ///
+ public static string chkDumpAnalyzerJson {
+ get {
+ return ResourceManager.GetString("chkDumpAnalyzerJson", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to When exporting, export copies of saves.
///
@@ -348,6 +357,24 @@ public static string chkOpacity_note_Text {
}
}
+ ///
+ /// Looks up a localized string similar to Log Performance metrics.
+ ///
+ public static string chkReportPerformance {
+ get {
+ return ResourceManager.GetString("chkReportPerformance", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Log Player debug info.
+ ///
+ public static string chkReportPlayerInfo {
+ get {
+ return ResourceManager.GetString("chkReportPlayerInfo", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Show zone connections.
///
@@ -546,6 +573,24 @@ public static string Date {
}
}
+ ///
+ /// Looks up a localized string similar to Debug.
+ ///
+ public static string Debug {
+ get {
+ return ResourceManager.GetString("Debug", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Enabling these could cause performance degradation and flood the logs.
+ ///
+ public static string debug_note {
+ get {
+ return ResourceManager.GetString("debug_note", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Delete.
///
diff --git a/Remnant2SaveAnalyzer/locales/Strings.resx b/Remnant2SaveAnalyzer/locales/Strings.resx
index 4754961..618f74b 100644
--- a/Remnant2SaveAnalyzer/locales/Strings.resx
+++ b/Remnant2SaveAnalyzer/locales/Strings.resx
@@ -534,4 +534,19 @@
Show campaign/adventure items with a missing prerequisite that did not roll in the compaign/adventure
+
+ Dump Analyzer data structures to analyzer.json
+
+
+ Log Performance metrics
+
+
+ Log Player debug info
+
+
+ Debug
+
+
+ Enabling these could cause performance degradation and flood the logs
+
\ No newline at end of file