diff --git a/SoG_SGreader/ComandLineOptions.cs b/SoG_SGreader/ComandLineOptions.cs index bd35764..9929b5b 100644 --- a/SoG_SGreader/ComandLineOptions.cs +++ b/SoG_SGreader/ComandLineOptions.cs @@ -4,13 +4,14 @@ namespace SoG_SGreader { class ComandLineOptions { - [Value(0, MetaName = "savegame path", Required = false, HelpText = "Path to the savegame")] + [Value(0, MetaName = "savegame path", HelpText = "Path to the savegame", Required = false)] public string SavegamePath { get; set; } [Option('t', "text", HelpText = "Show a short summary of the savegame")] public bool ShowText { get; set; } - [Option('j', "json", HelpText = "Print json of the savegame to console")] + //specify the json option and the path to the savegame + [Option('j', "json", HelpText = "Show the savegame as json")] public bool ShowJson { get; set; } [Option('h', "help", HelpText = "Show help")] diff --git a/SoG_SGreader/DataReader.cs b/SoG_SGreader/DataReader.cs index 952b273..29f7fe4 100644 --- a/SoG_SGreader/DataReader.cs +++ b/SoG_SGreader/DataReader.cs @@ -4,7 +4,7 @@ namespace SoG_SGreader { - public class DataReader + public static class DataReader { public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole) { @@ -16,7 +16,9 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole) txtConsole.AppendText("\r\nFilesize: " + new FileInfo(fileName).Length); - playerObject.MagicByte = readBinary.ReadInt32(); //I dont know yet what the first bytes stand for tbh + playerObject.MagicByte = readBinary.ReadInt32(); //I dont know yet what the first bytes stand for tbh + + //TODO: Cast to SogItems playerObject.Equip.Hat = readBinary.ReadInt32(); playerObject.Equip.Facegear = readBinary.ReadInt32(); playerObject.Style.Bodytype = readBinary.ReadChar(); //seems like always B ? @@ -35,6 +37,7 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole) playerObject.Style.HatHidden = readBinary.ReadBoolean(); //[Sog_PlayerProperty(16)] playerObject.Style.FacegearHidden = readBinary.ReadBoolean(); + //TODO: Cast to SogItems playerObject.LastTwoHander = readBinary.ReadInt32(); //last equipped onehander? playerObject.LastOneHander = readBinary.ReadInt32(); //last equipped twohander? playerObject.LastBow = readBinary.ReadInt32(); //last equipped bow? @@ -370,5 +373,65 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole) return playerObject; } + + public static string GetCharName(string fileName) + { + using (FileStream fileStream = new FileStream(fileName, FileMode.Open)) + { + BinaryReader readBinary = new BinaryReader(fileStream); + + readBinary.ReadInt32(); //I dont know yet what the first bytes stand for tbh + readBinary.ReadInt32(); //pPlayer.equip.Hat = + readBinary.ReadInt32(); //pPlayer.equip.Facegear = + readBinary.ReadChar(); // pPlayer.style.Bodytype = + readBinary.ReadInt32(); //pPlayer.style.Hair = + readBinary.ReadInt32(); //pPlayer.equip.Weapon = + readBinary.ReadInt32(); //pPlayer.equip.Shield = + readBinary.ReadInt32(); //pPlayer.equip.Armor = + readBinary.ReadInt32(); //pPlayer.equip.Shoes = + readBinary.ReadInt32(); //pPlayer.equip.Accessory1 = + readBinary.ReadInt32(); //pPlayer.equip.Accessory2 = + readBinary.ReadInt32(); //pPlayer.style.Hat = + readBinary.ReadInt32(); //pPlayer.style.Facegear = + readBinary.ReadInt32(); //pPlayer.style.Weapon = + readBinary.ReadInt32(); //pPlayer.style.Shield = + + readBinary.ReadBoolean(); //pPlayer.style.HatHidden = + readBinary.ReadBoolean(); //pPlayer.style.FacegearHidden = + + readBinary.ReadInt32(); //pPlayer.LastTwoHander = + readBinary.ReadInt32(); //pPlayer.LastOneHander = + readBinary.ReadInt32(); //pPlayer.LastBow = + + for (int i = 0; i < 10; i++) + { + int quckslotType = readBinary.ReadByte(); + if (quckslotType == 1) + { + readBinary.ReadInt32(); //pPlayer.quickslots.Add((Sog_Items) + } + else if (quckslotType == 2) + { + readBinary.ReadUInt16(); //pPlayer.quickslots.Add((Sog_Spells) + } + else + { + + } + } + + readBinary.ReadByte(); //pPlayer.style.HairColor = + readBinary.ReadByte(); //pPlayer.style.SkinColor = + readBinary.ReadByte(); //pPlayer.style.PonchoColor = + readBinary.ReadByte(); // pPlayer.style.ShirtColor = + readBinary.ReadByte(); //pPlayer.style.PantsColor = + + readBinary.ReadByte(); //pPlayer.style.Sex = + string nickname = readBinary.ReadString(); + readBinary.Dispose(); + + return nickname; + } + } } } diff --git a/SoG_SGreader/Forms/FrmLoadSaveGame.cs b/SoG_SGreader/Forms/FrmLoadSaveGame.cs index 50b0e24..c91ff2f 100644 --- a/SoG_SGreader/Forms/FrmLoadSaveGame.cs +++ b/SoG_SGreader/Forms/FrmLoadSaveGame.cs @@ -28,68 +28,7 @@ private void BtnLoadSaveGame_Click(object sender, EventArgs e) frmMain.ShowDialog(); this.Close(); } - - private string GetCharName(string fileName) // shouldnt be in that class here - { - using (FileStream fileStream = new FileStream(fileName, FileMode.Open)) - { - - BinaryReader readBinary = new BinaryReader(fileStream); - - readBinary.ReadInt32(); //I dont know yet what the first bytes stand for tbh - readBinary.ReadInt32(); //pPlayer.equip.Hat = - readBinary.ReadInt32(); //pPlayer.equip.Facegear = - readBinary.ReadChar(); // pPlayer.style.Bodytype = - readBinary.ReadInt32(); //pPlayer.style.Hair = - readBinary.ReadInt32(); //pPlayer.equip.Weapon = - readBinary.ReadInt32(); //pPlayer.equip.Shield = - readBinary.ReadInt32(); //pPlayer.equip.Armor = - readBinary.ReadInt32(); //pPlayer.equip.Shoes = - readBinary.ReadInt32(); //pPlayer.equip.Accessory1 = - readBinary.ReadInt32(); //pPlayer.equip.Accessory2 = - readBinary.ReadInt32(); //pPlayer.style.Hat = - readBinary.ReadInt32(); //pPlayer.style.Facegear = - readBinary.ReadInt32(); //pPlayer.style.Weapon = - readBinary.ReadInt32(); //pPlayer.style.Shield = - - readBinary.ReadBoolean(); //pPlayer.style.HatHidden = - readBinary.ReadBoolean(); //pPlayer.style.FacegearHidden = - - readBinary.ReadInt32(); //pPlayer.LastTwoHander = - readBinary.ReadInt32(); //pPlayer.LastOneHander = - readBinary.ReadInt32(); //pPlayer.LastBow = - - for (int i = 0; i < 10; i++) - { - int quckslotType = readBinary.ReadByte(); - if (quckslotType == 1) - { - readBinary.ReadInt32(); //pPlayer.quickslots.Add((Sog_Items) - } - else if (quckslotType == 2) - { - readBinary.ReadUInt16(); //pPlayer.quickslots.Add((Sog_Spells) - } - else - { - - } - } - - readBinary.ReadByte(); //pPlayer.style.HairColor = - readBinary.ReadByte(); //pPlayer.style.SkinColor = - readBinary.ReadByte(); //pPlayer.style.PonchoColor = - readBinary.ReadByte(); // pPlayer.style.ShirtColor = - readBinary.ReadByte(); //pPlayer.style.PantsColor = - - readBinary.ReadByte(); //pPlayer.style.Sex = - string nickname = readBinary.ReadString(); - readBinary.Dispose(); - - return nickname; - } - } - + private void GetSaveGameFiles(string sFilePath) { lstvSaveGames.Items.Clear(); @@ -98,7 +37,7 @@ private void GetSaveGameFiles(string sFilePath) string savegame = Path.Combine(sFilePath, i + ".cha"); if (File.Exists(savegame)) { - string[] item = new string[] { i + ".cha", GetCharName(savegame)}; + string[] item = new string[] { i + ".cha", DataReader.GetCharName(savegame)}; lstvSaveGames.Items.Add(new ListViewItem(item, 0)); } } diff --git a/SoG_SGreader/GamePatchReader.cs b/SoG_SGreader/GamePatchReader.cs index 2f99602..774ae9b 100644 --- a/SoG_SGreader/GamePatchReader.cs +++ b/SoG_SGreader/GamePatchReader.cs @@ -6,18 +6,19 @@ namespace SoG_SGreader { - class GamePatchReader + static class GamePatchReader { public static async Task GetCurrentGamePatchAsync(ITextBoxWrapper txtConsole) { string gameDataPath = GetGameDataPath(txtConsole); - if (string.IsNullOrEmpty(gameDataPath)) + if (string.IsNullOrEmpty(gameDataPath) || !Directory.Exists(gameDataPath)) { txtConsole.AppendText("\r\nGame data folder not found under: " + gameDataPath); return "?.???a"; } txtConsole.AppendText("\r\nGame data folder located: " + gameDataPath); + string exeFile = Path.Combine(gameDataPath, "Secrets Of Grindea.exe"); if (!File.Exists(exeFile)) @@ -33,30 +34,24 @@ private static string GetGameDataPath(ITextBoxWrapper txtConsole) { PlatformID pid = Environment.OSVersion.Platform; - if (pid == PlatformID.Win32NT || pid == PlatformID.Win32S || pid == PlatformID.Win32Windows || pid == PlatformID.WinCE) + switch (pid) { - // Windows-specific code - txtConsole.AppendText("\r\nOS: Windows"); - string steamPath = (string)Microsoft.Win32.Registry.GetValue(@"HKEY_CURRENT_USER\Software\Valve\Steam", "SteamPath", null); - return Path.Combine(steamPath, "steamapps", "common", "SecretsOfGrindea"); - } - else if (pid == PlatformID.Unix) - { - // Linux-specific code - txtConsole.AppendText("\r\nOS: Linux"); - return Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".local", "share", "Steam", "steamapps", "common", "SecretsOfGrindea"); - } - else if (pid == PlatformID.MacOSX) - { - // MacOSX-specific code - txtConsole.AppendText("\r\nOS: MacOSX"); - return Path.Combine(Environment.GetEnvironmentVariable("HOME"), "Library", "Application Support", "Steam", "steamapps", "common", "SecretsOfGrindeaa"); - } - else - { - // Unknown OS - txtConsole.AppendText("\r\nOS: Unknown"); - return null; + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + case PlatformID.WinCE: + txtConsole.AppendText("\r\nOS: Windows"); + string steamPath = (string)Microsoft.Win32.Registry.GetValue(@"HKEY_CURRENT_USER\Software\Valve\Steam", "SteamPath", null); + return Path.Combine(steamPath, "steamapps", "common", "SecretsOfGrindea"); + case PlatformID.Unix: + txtConsole.AppendText("\r\nOS: Linux"); + return Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".local", "share", "Steam", "steamapps", "common", "SecretsOfGrindea"); + case PlatformID.MacOSX: + txtConsole.AppendText("\r\nOS: MacOSX"); + return Path.Combine(Environment.GetEnvironmentVariable("HOME"), "Library", "Application Support", "Steam", "steamapps", "common", "SecretsOfGrindeaa"); + default: + txtConsole.AppendText("\r\nOS: Unknown"); + return null; } } @@ -112,7 +107,5 @@ private static string GetLatestGamePatch(string exeFilePath, ITextBoxWrapper txt } return "?.???a"; } - - } } diff --git a/SoG_SGreader/JsonHandler.cs b/SoG_SGreader/JsonHandler.cs index 8984984..7b9070a 100644 --- a/SoG_SGreader/JsonHandler.cs +++ b/SoG_SGreader/JsonHandler.cs @@ -1,10 +1,11 @@ using System; using System.IO; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace SoG_SGreader { - public class JsonHandler + public static class JsonHandler { private static bool IsDirectory(string jsonFilePath) { @@ -17,12 +18,14 @@ private static bool IsDirectory(string jsonFilePath) return false; } } + public static string SaveGameToJson(Player player, string jsonFilePath) { JsonSerializer serializer = new JsonSerializer(); serializer.NullValueHandling = NullValueHandling.Include; serializer.Formatting = Formatting.Indented; - + serializer.Converters.Add(new StringEnumConverter()); + string jsonPath = jsonFilePath; if (IsDirectory(jsonFilePath)) @@ -52,14 +55,26 @@ public static string GetJson(Player player) JsonSerializer serializer = new JsonSerializer(); serializer.NullValueHandling = NullValueHandling.Include; serializer.Formatting = Formatting.Indented; - - StringWriter sw = new StringWriter(); - using (JsonWriter writer = new JsonTextWriter(sw)) + serializer.Converters.Add(new StringEnumConverter()); // TODO: make this optional + try { - serializer.Serialize(writer, player); - } + StringWriter sw = new StringWriter(); + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, player); + } + return sw.ToString(); - return sw.ToString(); + } + catch (Exception e) + { + StringWriter sw = new StringWriter(); + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, e); + } + return sw.ToString(); + } } } } \ No newline at end of file diff --git a/SoG_SGreader/Program.cs b/SoG_SGreader/Program.cs index 08c346e..5687a2e 100644 --- a/SoG_SGreader/Program.cs +++ b/SoG_SGreader/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; using System.Windows.Forms; using SoG_SGreader.Wrapper; using CommandLine; @@ -7,15 +8,33 @@ namespace SoG_SGreader { public static class Program { - [STAThread] - static void Main(string[] args) + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool AllocConsole(); + + public static void Main(string[] args) { + if (args.Length <= 0) + { + RunApp(); + return; + } + + PlatformID pid = Environment.OSVersion.Platform; + // If on Windows, allocate a console. + if (pid == PlatformID.Win32NT || pid == PlatformID.Win32S || + pid == PlatformID.Win32Windows || pid == PlatformID.WinCE) + { + AllocConsole(); + } + Parser.Default .ParseArguments(args) .WithParsed(RunOptions); + } - static void RunOptions(ComandLineOptions opts) + private static void RunOptions(ComandLineOptions opts) { if (opts.ShowText) { @@ -35,7 +54,7 @@ static void RunOptions(ComandLineOptions opts) } } - public static void DisplayTextSummary(string savegamePath) + private static void DisplayTextSummary(string savegamePath) { if (string.IsNullOrEmpty(savegamePath)) { @@ -50,11 +69,19 @@ public static void DisplayTextSummary(string savegamePath) } catch (Exception e) { - Console.WriteLine(e.Message); + try // nested try-catch to handle broken pipe + { + Console.WriteLine("Could not read savegame."); + Console.WriteLine(e.Message); + } + catch (Exception) + { + // ignored, since we cant write to the console anymore + } } } - public static void DisplayJson(string savegamePath) + private static void DisplayJson(string savegamePath) { if (string.IsNullOrEmpty(savegamePath)) { @@ -71,11 +98,19 @@ public static void DisplayJson(string savegamePath) } catch (Exception e) { - Console.WriteLine(e.Message); + try // nested try-catch to handle broken pipe + { + Console.WriteLine("Could not read savegame."); + Console.WriteLine(e.Message); + } + catch (Exception) + { + // ignored, since we cant write to the console anymore + } } } - public static void RunApp() + private static void RunApp() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);