Skip to content

Commit

Permalink
added CommandLineParser
Browse files Browse the repository at this point in the history
  • Loading branch information
tolik518 committed Oct 22, 2023
1 parent 9d4c1b8 commit 9c8c81f
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 41 deletions.
30 changes: 26 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
# SoG Savegame Editor ![Icon](https://returnnull.de/images/_64.png)
![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/tolik518/SoG_SGreader?label=latest%20version&style=flat-square) ![GitHub all releases](https://img.shields.io/github/downloads/tolik518/SoG_SGreader/total?style=flat-square)

## Download
Head over to the releases if you are just here for the [download link](https://github.com/tolik518/SoG_SGreader/releases), then press on `Assets`
on the latest version and download the `SoG_SGreader.exe` file
on the latest version and download the `SoG_SGreader.exe` file.

Or just [press here](https://github.com/tolik518/SoG_SGreader/releases/latest/download/SoG_SGreader.exe) to download the latest version.

## How to use
![SoG_SGreader](https://returnnull.de/images/SoG_SGreader7.png)

**SoG Savegame Editor** is a work in progress tool for editing [Secrets of Grindea](https://store.steampowered.com/app/269770/Secrets_of_Grindea/) savegames.
Currenty it can only edit character files.
You can edit your nickname, skill points, gold, equipment, inventory, your pets and much more is comming!
You can just run the exe and it will open a file dialog where you can select your savegame file.
After that you can edit your savegame and save it back to the same file.

Alternatively you can drag and drop your savegame file on the exe and it will open the savegame directly.

You can also use the command line to open a savegame file directly.
```
SoG_SGreader.exe <savegame path> # Open UI with savegame, path to savegame is optional
SoG_SGreader.exe --help # Show help
SoG_SGreader.exe --patch # Show the supported game version
SoG_SGreader.exe --version # Show the version of the program
SoG_SGreader.exe --json <savegame path> # Print json of the savegame to console
SoG_SGreader.exe --text <savegame path> # Show a short summary of the savegame
```

## Description


**SoG Savegame Editor** is a tool for editing [Secrets of Grindea](https://store.steampowered.com/app/269770/Secrets_of_Grindea/) savegames.
You can edit your nickname, skill points, gold, equipment, inventory, your pets and much more is coming!

If you are interested how the save game file is build, you can find the structure
of the save game on the [wiki page](https://github.com/tolik518/SoG_SGreader/wiki/Savegame-File-Structure) (not actively maintained).
Expand Down
141 changes: 141 additions & 0 deletions SoG_SGreader.Test/IntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
using System;
using System.Diagnostics;
using System.IO;
using Xunit;

namespace SoG_SGreader.Test
{
public class IntegrationTests
{
private static string GetExePath()
{
string projectDirectory = Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).Parent.Parent.Parent.FullName;

// Exception for GitHub Actions Test Runner
if (Environment.GetEnvironmentVariable("GITHUB_WORKSPACE") != null) {
projectDirectory = Environment.GetEnvironmentVariable("GITHUB_WORKSPACE");
}

return Path.Combine(projectDirectory, "SoG_SGreader", "bin", "Debug", "SoG_SGreader.exe");
}

private static string GetSaveGamePath(string saveGameNumber)
{
string projectDirectory = Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).Parent.Parent.Parent.FullName;

// Exception for GitHub Actions Test Runner
if (Environment.GetEnvironmentVariable("GITHUB_WORKSPACE") != null) {
projectDirectory = Environment.GetEnvironmentVariable("GITHUB_WORKSPACE");
}

return Path.Combine(projectDirectory, "SoG_SGreader.Test", "SaveGames", saveGameNumber + ".cha");
}


[Fact]
public void TestSavegameTextOutput()
{
string arguments = "-t " + GetSaveGamePath("1");

// Start the process
using var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = GetExePath(),
Arguments = arguments,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};

process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Assert.Contains("Filesize: 4494", output);
Assert.Contains("Birthday: 24.6.1081", output);
Assert.Contains("ItemsMetCount: 124", output);
Assert.Contains("KilledEnemiesCount: 58", output);
}

[Fact]
public void TestSavegameJsonOutput()
{
string arguments = "-j " + GetSaveGamePath("1");

// Start the process
using var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = GetExePath(),
Arguments = arguments,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};

process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Assert.Contains("\"MagicByte\": 116", output);
Assert.Contains("\"PlayTimeTotal\": 1645950", output);
Assert.Contains("\"UniquePlayerId\": 451873", output);
Assert.Contains("\"Cash\": 6873538", output);
}

[Fact]
public void TestPatchOutput()
{
string arguments = "--patch";

// Start the process
using var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = GetExePath(),
Arguments = arguments,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};

process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Assert.Contains(FrmMain.CurrentPatch, output);
}

[Fact]
public void TestHelpOutput()
{
string arguments = "--help";

// Start the process
using var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = GetExePath(),
Arguments = arguments,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};

process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Assert.Contains("--help", output);
}
}
}
2 changes: 2 additions & 0 deletions SoG_SGreader.Test/SoG_SGreader.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<AssemblyName>SoG_SGreader.Test</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<LangVersion>8</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down Expand Up @@ -67,6 +68,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DataReaderTests.cs" />
<Compile Include="IntegrationTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs"/>
</ItemGroup>
<ItemGroup>
Expand Down
8 changes: 7 additions & 1 deletion SoG_SGreader/DataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole)
playerObject.Style.PantsColor = readBinary.ReadByte();

playerObject.Style.Sex = readBinary.ReadByte(); // female = 0; male = 1
txtConsole.AppendText("\r\nGender: " + playerObject.Style.Sex);

playerObject.NicknameLength = readBinary.ReadByte();

playerObject.Nickname = new string(readBinary.ReadChars(playerObject.NicknameLength));
txtConsole.AppendText("\r\nNickname: " + playerObject.Nickname);

playerObject.ItemsCount = readBinary.ReadInt32();

Expand Down Expand Up @@ -146,6 +148,7 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole)
txtConsole.AppendText("\r\nSkillCount: " + playerObject.SkillsCount);

playerObject.Level = readBinary.ReadInt16(); //Level
txtConsole.AppendText("\r\nLevel: " + playerObject.Level);

playerObject.ExpCurrent = readBinary.ReadInt32(); //currentexp
playerObject.ExpUnknown0 = readBinary.ReadInt32(); //something exp ?
Expand All @@ -155,6 +158,7 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole)
playerObject.SkillSilverPoints = readBinary.ReadInt16(); //Silver Skill Points
playerObject.SkillGoldPoints = readBinary.ReadInt16(); //Gold Skill Points
playerObject.Cash = readBinary.ReadInt32(); //cash
txtConsole.AppendText("\r\nCash: " + playerObject.Cash);

playerObject.PetsCount = readBinary.ReadByte();
txtConsole.AppendText("\r\nPetsCount: " + playerObject.PetsCount);
Expand Down Expand Up @@ -287,6 +291,7 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole)

playerObject.PotionsMax = readBinary.ReadByte();
txtConsole.AppendText("\r\n" + "PotionsMax: " + playerObject.PotionsMax);

playerObject.PotionsEquipped = readBinary.ReadByte();
txtConsole.AppendText("\r\n" + "PotionsEquipped: " + playerObject.PotionsEquipped);

Expand All @@ -307,7 +312,7 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole)
playerObject.UnknownVariable04 = readBinary.ReadInt32();
playerObject.UnknownVariable05 = readBinary.ReadInt32();
playerObject.PlayTimeTotal = readBinary.ReadInt32();
txtConsole.AppendText("\r\nPlayTimeTotal: " + (double)playerObject.PlayTimeTotal / 60 / 60 / 60 + " hours");
txtConsole.AppendText("\r\nPlayTimeTotal: " + Math.Round((double)playerObject.PlayTimeTotal / 60 / 60 / 60, 2) + " hours");
playerObject.UnknownVariable06 = readBinary.ReadByte();

playerObject.UnknownVariable07Count = readBinary.ReadInt16();
Expand Down Expand Up @@ -358,6 +363,7 @@ public static Player ReadFromFile(string fileName, ITextBoxWrapper txtConsole)

txtConsole.AppendText("\r\nLength: " + readBinary.BaseStream.Length);
txtConsole.AppendText("\r\nPosition: " + readBinary.BaseStream.Position);
txtConsole.AppendText("\r\nIs Position and length the same?: " + (readBinary.BaseStream.Position == readBinary.BaseStream.Length).ToString());

readBinary.Close();
fileStream.Close();
Expand Down
2 changes: 1 addition & 1 deletion SoG_SGreader/Forms/FrmMain.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions SoG_SGreader/Forms/FrmMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace SoG_SGreader
{
public partial class FrmMain : Form
{
public static readonly string CurrentPatch = "Patch 0.949a";
private Player playerObject = new Player();
private readonly ComboBox[] cbQuickslot = new ComboBox[10];
private readonly ComboBox[] cbQuickslotType = new ComboBox[10];
Expand Down
Loading

0 comments on commit 9c8c81f

Please sign in to comment.