1
0
mirror of https://github.com/soarqin/DSP_Mods_TO.git synced 2026-02-04 22:22:22 +08:00

Compare commits

..

5 Commits

Author SHA1 Message Date
98abc31c6f format code 2026-01-28 20:27:15 +08:00
d698e0afc1 minor fix 2026-01-28 20:18:11 +08:00
8077f7fa30 CompressSave 1.3.8 2026-01-25 15:49:39 +08:00
fbad19f68f refenrence publicized dlls 2026-01-25 13:43:17 +08:00
471cf7d013 use local references 2026-01-25 13:43:02 +08:00
46 changed files with 2433 additions and 2319 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -1,177 +1,137 @@
## Changelog <details>
<summary>Read me in English</summary>
### 1.3.7 ## Changelog
* 1.3.8
* Support for game version 0.10.34.
* 1.3.7
* Remove use of MonoMod.Util on loading dll import functions to make mod compatible with HarmonyX 2.13.0 (Although it is not merged yet. Check the PR [here](https://github.com/BepInEx/BepInEx/pull/902)). * Remove use of MonoMod.Util on loading dll import functions to make mod compatible with HarmonyX 2.13.0 (Although it is not merged yet. Check the PR [here](https://github.com/BepInEx/BepInEx/pull/902)).
### 1.3.6 * 1.3.6
* Support for using subfolder in save filepath (only MODs are doing this currently). * Support for using subfolder in save filepath (only MODs are doing this currently).
### 1.3.5 * 1.3.5
* Fix a crash issue on choosing language other than English and Chinese. * Fix a crash issue on choosing language other than English and Chinese.
### 1.3.4 * 1.3.4
* Support for game version 0.10.28.20759. * Support for game version 0.10.28.20759.
### 1.3.3 * 1.3.3
* Fix a display issue on combobox of compression type. * Fix a display issue on combobox of compression type.
### 1.3.2 * 1.3.2
* Add config UI on Save Game dialog, to set compression types. * Add config UI on Save Game dialog, to set compression types. * Change button text to `Save (Compress)` for better understanding.
* Change button text to `Save (Compress)` for better understanding.
### 1.3.1 * 1.3.1
* Add config to disable feature for auto saves. * Add config to disable feature for auto saves. * Fix bug that first save after game start is always compressed in Zstd.
* Fix bug that first save after game start is always compressed in Zstd.
### 1.3.0 * 1.3.0
* Separate config entries for manual save and auto save. * Separate config entries for manual save and auto save. * Now you can still get speed benefit while setting compression type to `None` for auto saves, and for manual saves if using the new `Save` button. * Adds a `nonewrap.dll` for this function. * Update `LZ4` and `Zstd` library to latest version. * `lz4wrap.dll` and `zstdwrap.dll` are compiled using `-O3` instead of `-Os`, expect to be slightly faster but larger.
* Now you can still get speed benefit while setting compression type to `None` for auto saves, and for manual saves if using the new `Save` button.
+ Adds a `nonewrap.dll` for this function.
* Update `LZ4` and `Zstd` library to latest version.
* `lz4wrap.dll` and `zstdwrap.dll` are compiled using `-O3` instead of `-Os`, expect to be slightly faster but larger.
<details> <details>
<summary>Older versions</summary> <summary>Older versions</summary>
### 1.2.2 * 1.2.2
* Fix #4, a bug caused by non-ASCII UTF-8 characters. * Fix #4, a bug caused by non-ASCII UTF-8 characters. * Remove use of Harmony.UnpatchAll() to avoid warnings in BepInEx log.
* Remove use of Harmony.UnpatchAll() to avoid warnings in BepInEx log.
### 1.2.1 * 1.2.1
* Simplified codes to display compression type and `Decompress` button on save/load UI, making CompressSave compatible with other MODs(like GalacticScale) which override `UILoadGameWindow::OnSelectedChange()`. * Simplified codes to display compression type and `Decompress` button on save/load UI, making CompressSave compatible with other MODs(like GalacticScale) which override `UILoadGameWindow::OnSelectedChange()`. * Add compression level -5 to -1 for zstd, which makes it working better than lz4(which is actually lz4hc used by lz4frame) now: * -5 gets faster compression speed than lz4 with still a little better compression ratio. * -1 has almost the same speed against lz4 with greater compression ratio. * Due to bug of r2modman UI which does not support negative integer, the config value of compression level is not limited any more. * move native wrapper DLLs into `x64` folder to avoid warning logs on loading BepInEx plugins.
* Add compression level -5 to -1 for zstd, which makes it working better than lz4(which is actually lz4hc used by lz4frame) now:
* -5 gets faster compression speed than lz4 with still a little better compression ratio.
* -1 has almost the same speed against lz4 with greater compression ratio.
* Due to bug of r2modman UI which does not support negative integer, the config value of compression level is not limited any more.
* move native wrapper DLLs into `x64` folder to avoid warning logs on loading BepInEx plugins.
### 1.2.0 * 1.2.0
* Match game version 0.9.27.15033. * Match game version 0.9.27.15033. * Add new compression type: zstd (a bit slower but get better compression ratio than lz4). * Add config to set compression type and level(Don't use high compression levels for zstd as they are very slow). * Hide decompress button for normal save files. * Optimize native dlls for other compression library support: * Unified naming rules for filenames and export functions. * Add compression level support.
* Add new compression type: zstd (a bit slower but get better compression ratio than lz4).
* Add config to set compression type and level(Don't use high compression levels for zstd as they are very slow).
* Hide decompress button for normal save files.
* Optimize native dlls for other compression library support:
* Unified naming rules for filenames and export functions.
* Add compression level support.
### 1.1.14 * 1.1.14
* Fix Sandbox info on Save/Load Panel. * Fix Sandbox info on Save/Load Panel. * Fix DLL version info.
* Fix DLL version info.
### 1.1.13 * 1.1.13
* Match game version 0.9.26.13026. * Move "Sandbox Mode" checkbox on Save Panel to avoid overlap. * Avoid warning message on "Continue" button of main menu.
* Match game version 0.9.26.13026.
* Move "Sandbox Mode" checkbox on Save Panel to avoid overlap.
* Avoid warning message on "Continue" button of main menu.
### 1.1.12
* 1.1.12
* Match game version 0.9.25.12007. * Match game version 0.9.25.12007.
### 1.1.11 * 1.1.11
* Fix 1.1.10 package issue. * Fix 1.1.10 package issue.
### 1.1.10 * 1.1.10
* Fix 1.1.8 Archive corruption with DIY System, corrupted archives can be fixed by using \[Fix118\] mod * Fix 1.1.8 Archive corruption with DIY System, corrupted archives can be fixed by using \[Fix118\] mod
Fix118: https://github.com/bluedoom/DSP_Mod/blob/master/Fix118 Fix118: <https://github.com/bluedoom/DSP_Mod/blob/master/Fix118>
### 1.1.9
* 1.1.9
* CompressSave is temporarily disabled due to some error with the DIY system. * CompressSave is temporarily disabled due to some error with the DIY system.
### 1.1.8 * 1.1.8
* Match game version 0.9.24.11029 * Match game version 0.9.24.11029
### 1.1.7 * 1.1.7
* Fix incorrect data on statistic panel. * Improve performance.
* Fix incorrect data on statistic panel.
* Improve performance.
### 1.1.6
* 1.1.6
* fix memory leak * fix memory leak
### 1.1.5 (Game Version 0.8.22) * 1.1.5 (Game Version 0.8.22)
* Match game version 0.8.22. * Thanks [@starfi5h] for * PatchSave now use transpiler for better robustness. * Change version check to soft warning. * Add PeekableReader so other mods can use BinaryReader.PeekChar(). * Change LZ4DecompressionStream.Position behavior. Position setter i - available now.
* Match game version 0.8.22.
* Thanks [@starfi5h] for
- PatchSave now use transpiler for better robustness.
- Change version check to soft warning.
- Add PeekableReader so other mods can use BinaryReader.PeekChar().
- Change LZ4DecompressionStream.Position behavior. Position setter i - available now.
### 1.1.4 (Game Version 0.8.19)
* 1.1.4 (Game Version 0.8.19)
* Match game version 0.8.19. * Match game version 0.8.19.
### 1.1.3 (2021/05/29) (Game Version 0.7.18) * 1.1.3 (2021/05/29) (Game Version 0.7.18)
* Match game version 0.7.18. * Fix memory leak.
* Match game version 0.7.18.
* Fix memory leak.
### 1.1.2 (2021/03/24) (Game Version 0.6.17)
* 1.1.2 (2021/03/24) (Game Version 0.6.17)
* Handle lz4 library missing Error * Handle lz4 library missing Error
### 1.1.1 (2021/03/17) (Game Version 0.6.17) * 1.1.1 (2021/03/17) (Game Version 0.6.17)
* Fix Load Error * Fix Load Error
### 1.1.0 (2021/03/17) (Game Version 0.6.17) * 1.1.0 (2021/03/17) (Game Version 0.6.17)
* Add UI button * Add UI button
</details> </details>
</details>
<details>
<summary>中文读我</summary>
## 更新日志 ## 更新日志
### 1.3.7 * 1.3.8
* 支持游戏版本 0.10.34。
* 1.3.7
* 移除使用MonoMod.Util加载dll导入函数以使MOD与HarmonyX 2.13.0兼容(尽管此改动尚未合并。[在此](https://github.com/BepInEx/BepInEx/pull/902)查看合并请求)。 * 移除使用MonoMod.Util加载dll导入函数以使MOD与HarmonyX 2.13.0兼容(尽管此改动尚未合并。[在此](https://github.com/BepInEx/BepInEx/pull/902)查看合并请求)。
### 1.3.6 * 1.3.6
* 支持在存档路径中使用子文件夹(目前只有MOD会这么干)。 * 支持在存档路径中使用子文件夹(目前只有MOD会这么干)。
### 1.3.5 * 1.3.5
* 修复了选择英文和中文以外的语言时的崩溃问题。 * 修复了选择英文和中文以外的语言时的崩溃问题。
### 1.3.4 * 1.3.4
* 支持游戏版本 0.10.28.20759。 * 支持游戏版本 0.10.28.20759。
### 1.3.3 * 1.3.3
* 修复压缩类型下拉框显示问题。 * 修复压缩类型下拉框显示问题。
### 1.3.2 * 1.3.2
* 在保存面板上增加设置压缩方式的UI。 * 在保存面板上增加设置压缩方式的UI。 * 将按钮文本改为`压缩保存`以区分功能。
* 将按钮文本改为`压缩保存`以区分功能。
### 1.3.1 * 1.3.1
* 增加在自动存档中禁用压缩的设置项。 * 增加在自动存档中禁用压缩的设置项。 * 修复一个导致游戏开始后第一次保存总是使用Zstd压缩的bug。
* 修复一个导致游戏开始后第一次保存总是使用Zstd压缩的bug。
### 1.3.0 * 1.3.0
* 分离手动存档和自动存档的设置项。 * 分离手动存档和自动存档的设置项。 * 现在在自动存档设置压缩类型为`存储`也可以获得速度提升,手动存档也可以在使用新的`保存`按钮后获得速度提升。 * 为此增加了`nonewrap.dll`* 更新`LZ4`和`Zstd`库到最新版本。 * `lz4wrap.dll``zstdwrap.dll`使用`-O3`编译而不是`-Os`,速度略有提升但体积变大。
* 现在在自动存档设置压缩类型为`存储`也可以获得速度提升,手动存档也可以在使用新的`保存`按钮后获得速度提升。
+ 为此增加了`nonewrap.dll`
* 更新`LZ4``Zstd`库到最新版本。
* `lz4wrap.dll``zstdwrap.dll`使用`-O3`编译而不是`-Os`,速度略有提升但体积变大。
<details> <details>
<summary>Older versions</summary> <summary>Older versions</summary>
### 1.2.2 * 1.2.2
* 修复 #4一个导致非ASCII UTF-8字符导致的bug。 * 修复 #4一个导致非ASCII UTF-8字符导致的bug。 * 移除使用Harmony.UnpatchAll()以避免在BepInEx日志中出现警告。
* 移除使用Harmony.UnpatchAll()以避免在BepInEx日志中出现警告。
### 1.2.1 * 1.2.1
* 简化代码以在存档读取面板上显示压缩类型和`解压`按钮使得CompressSave与其他MOD(如GalacticScale)兼容,因为它们都覆盖了`UILoadGameWindow::OnSelectedChange()` * 简化代码以在存档读取面板上显示压缩类型和`解压`按钮使得CompressSave与其他MOD(如GalacticScale)兼容,因为它们都覆盖了`UILoadGameWindow::OnSelectedChange()` * 为zstd添加了压缩等级-5到-1现在它比lz4(实际上是lz4frame)表现更好了: * -5比lz4更快但压缩比略有提升。 * -1和lz4几乎一样快但压缩比更高。 * 由于r2modman UI的bug压缩等级的设置项不再限制范围。 * 将本地的wrapper DLL移动到`x64`目录。
* 为zstd添加了压缩等级-5到-1现在它比lz4(实际上是lz4frame)表现更好了:
* -5比lz4更快但压缩比略有提升。
* -1和lz4几乎一样快但压缩比更高。
* 由于r2modman UI的bug压缩等级的设置项不再限制范围。
* 将本地的wrapper DLL移动到`x64`目录。
</details> </details>
</details>

View File

@@ -156,9 +156,16 @@ public class PatchSave
} }
} }
public static void UseCommonSaveCompressionType()
{
_compressionTypeForSaving = CompressionTypeForSaves;
_compressionLevelForSaving = CompressionLevelForSaves;
}
[HarmonyPrefix] [HarmonyPrefix]
[HarmonyPatch(typeof(GameSave), "AutoSave")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.AutoSave))]
[HarmonyPatch(typeof(GameSave), "SaveAsLastExit")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.AutoSaveAfterErrored))]
[HarmonyPatch(typeof(GameSave), nameof(GameSave.SaveAsLastExit))]
private static void BeforeAutoSave() private static void BeforeAutoSave()
{ {
UseCompressSave = EnableForAutoSaves.Value && EnableCompress; UseCompressSave = EnableForAutoSaves.Value && EnableCompress;
@@ -168,7 +175,7 @@ public class PatchSave
} }
[HarmonyTranspiler] [HarmonyTranspiler]
[HarmonyPatch(typeof(GameSave), "SaveCurrentGame")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.SaveCurrentGame))]
private static IEnumerable<CodeInstruction> SaveCurrentGame_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) private static IEnumerable<CodeInstruction> SaveCurrentGame_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{ {
/* BinaryWriter binaryWriter = new BinaryWriter(fileStream); => Create compressionStream and replace binaryWriter. /* BinaryWriter binaryWriter = new BinaryWriter(fileStream); => Create compressionStream and replace binaryWriter.
@@ -182,23 +189,23 @@ public class PatchSave
matcher.MatchForward(false, matcher.MatchForward(false,
new CodeMatch(OpCodes.Newobj, AccessTools.Constructor(typeof(BinaryWriter), [typeof(FileStream)])) new CodeMatch(OpCodes.Newobj, AccessTools.Constructor(typeof(BinaryWriter), [typeof(FileStream)]))
).Set( ).Set(
OpCodes.Call, AccessTools.Method(typeof(PatchSave), "CreateBinaryWriter") OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(CreateBinaryWriter))
).MatchForward(false, ).MatchForward(false,
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), "BeginStream")) new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), nameof(PerformanceMonitor.BeginStream)))
).Set( ).Set(
OpCodes.Call, AccessTools.Method(typeof(PatchSave), "MonitorStream") OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(MonitorStream))
).MatchForward(false, ).MatchForward(false,
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Stream), "Seek")) new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Stream), nameof(Stream.Seek)))
).Set( ).Set(
OpCodes.Call, AccessTools.Method(typeof(PatchSave), "FileLengthWrite0") OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(FileLengthWrite0))
).MatchForward(false, ).MatchForward(false,
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryWriter), "Write", [typeof(long)])) new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryWriter), nameof(BinaryWriter.Write), [typeof(long)]))
).Set( ).Set(
OpCodes.Call, AccessTools.Method(typeof(PatchSave), "FileLengthWrite1") OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(FileLengthWrite1))
).MatchForward(false, ).MatchForward(false,
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(IDisposable), "Dispose")) new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(IDisposable), nameof(IDisposable.Dispose)))
).Advance(1).Insert( ).Advance(1).Insert(
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "DisposeCompressionStream")) new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(DisposeCompressionStream)))
); );
EnableCompress = true; EnableCompress = true;
return matcher.InstructionEnumeration(); return matcher.InstructionEnumeration();
@@ -221,7 +228,6 @@ public class PatchSave
{ {
if (UseCompressSave) if (UseCompressSave)
{ {
SaveUtil.Logger.LogDebug("Begin compress save");
WriteHeader(fileStream); WriteHeader(fileStream);
_compressionStream = _compressionTypeForSaving switch _compressionStream = _compressionTypeForSaving switch
{ {
@@ -283,11 +289,11 @@ public class PatchSave
} }
[HarmonyTranspiler] [HarmonyTranspiler]
[HarmonyPatch(typeof(GameSave), "LoadCurrentGame")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.LoadCurrentGame))]
[HarmonyPatch(typeof(GameSave), "LoadGameDesc")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.LoadGameDesc))]
[HarmonyPatch(typeof(GameSave), "ReadHeader")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.ReadHeader))]
[HarmonyPatch(typeof(GameSave), "ReadHeaderAndDescAndProperty")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.ReadHeaderAndDescAndProperty))]
[HarmonyPatch(typeof(GameSave), "ReadModes")] [HarmonyPatch(typeof(GameSave), nameof(GameSave.ReadModes))]
private static IEnumerable<CodeInstruction> LoadCurrentGame_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator) private static IEnumerable<CodeInstruction> LoadCurrentGame_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{ {
/* using (BinaryReader binaryReader = new BinaryReader(fileStream)) => Create decompressionStream and replace binaryReader. /* using (BinaryReader binaryReader = new BinaryReader(fileStream)) => Create decompressionStream and replace binaryReader.
@@ -302,27 +308,27 @@ public class PatchSave
matcher.MatchForward(false, matcher.MatchForward(false,
new CodeMatch(OpCodes.Newobj, AccessTools.Constructor(typeof(BinaryReader), [typeof(FileStream)])) new CodeMatch(OpCodes.Newobj, AccessTools.Constructor(typeof(BinaryReader), [typeof(FileStream)]))
).Set( ).Set(
OpCodes.Call, AccessTools.Method(typeof(PatchSave), "CreateBinaryReader") OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(CreateBinaryReader))
).MatchForward(false, ).MatchForward(false,
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), "BeginStream")) new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(PerformanceMonitor), nameof(PerformanceMonitor.BeginStream)))
); );
if (matcher.IsValid) if (matcher.IsValid)
matcher.Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "MonitorStream")); matcher.Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(MonitorStream)));
matcher.Start().MatchForward(false, matcher.Start().MatchForward(false,
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryReader), "ReadInt64")) new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BinaryReader), nameof(BinaryReader.ReadInt64)))
).Set( ).Set(
OpCodes.Call, AccessTools.Method(typeof(PatchSave), "FileLengthRead") OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(FileLengthRead))
).MatchForward(false, ).MatchForward(false,
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(IDisposable), "Dispose")) new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(IDisposable), nameof(IDisposable.Dispose)))
).Advance(1).Insert( ).Advance(1).Insert(
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "DisposeCompressionStream")) new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(DisposeCompressionStream)))
).MatchBack(false, ).MatchBack(false,
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Stream), "Seek")) new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Stream), nameof(Stream.Seek)))
); );
if (matcher.IsValid) if (matcher.IsValid)
matcher.Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), "ReadSeek")); matcher.Set(OpCodes.Call, AccessTools.Method(typeof(PatchSave), nameof(ReadSeek)));
return matcher.InstructionEnumeration(); return matcher.InstructionEnumeration();
} }

View File

@@ -4,7 +4,7 @@
<AssemblyName>CompressSave</AssemblyName> <AssemblyName>CompressSave</AssemblyName>
<BepInExPluginGuid>org.soardev.compresssave</BepInExPluginGuid> <BepInExPluginGuid>org.soardev.compresssave</BepInExPluginGuid>
<Description>DSP MOD - CompressSave</Description> <Description>DSP MOD - CompressSave</Description>
<Version>1.3.7</Version> <Version>1.3.8</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
@@ -16,7 +16,7 @@
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" /> <PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" /> --> <!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" /> -->
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.*" /> <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.*" />
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" /> <PackageReference Include="UnityEngine.Modules" Version="2022.3.53" IncludeAssets="compile" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
@@ -27,6 +27,15 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>..\AssemblyFromGame\UnityEngine.UI.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'"> <ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" /> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup> </ItemGroup>

View File

@@ -9,7 +9,7 @@ class PatchUILoadGame
{ {
static UIButton _decompressButton; static UIButton _decompressButton;
[HarmonyPatch(typeof(UILoadGameWindow), "OnSelectedChange"), HarmonyPostfix] [HarmonyPatch(typeof(UILoadGameWindow), nameof(UILoadGameWindow.OnSelectedChange)), HarmonyPostfix]
private static void OnSelectedChange(UILoadGameWindow __instance) private static void OnSelectedChange(UILoadGameWindow __instance)
{ {
var selected = __instance.selected; var selected = __instance.selected;
@@ -26,7 +26,7 @@ class PatchUILoadGame
_decompressButton.gameObject.SetActive(compressedType != CompressionType.None); _decompressButton.gameObject.SetActive(compressedType != CompressionType.None);
} }
[HarmonyPatch(typeof(UILoadGameWindow), "_OnOpen"), HarmonyPostfix] [HarmonyPatch(typeof(UILoadGameWindow), nameof(UILoadGameWindow._OnOpen)), HarmonyPostfix]
static void _OnOpen(UILoadGameWindow __instance) static void _OnOpen(UILoadGameWindow __instance)
{ {
if (_decompressButton) return; if (_decompressButton) return;

View File

@@ -1,3 +1,4 @@
using CompressSave.UI;
using HarmonyLib; using HarmonyLib;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@@ -18,7 +19,7 @@ static class PatchUISaveGame
_OnDestroy(); _OnDestroy();
} }
[HarmonyPatch(typeof(UISaveGameWindow), "OnSelectedChange"), HarmonyPostfix] [HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow.OnSelectedChange)), HarmonyPostfix]
private static void OnSelectedChange(UISaveGameWindow __instance) private static void OnSelectedChange(UISaveGameWindow __instance)
{ {
var selected = __instance.selected; var selected = __instance.selected;
@@ -32,17 +33,17 @@ static class PatchUISaveGame
}; };
} }
[HarmonyPatch(typeof(UISaveGameWindow), "_OnDestroy"), HarmonyPostfix] [HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow._OnDestroy)), HarmonyPostfix]
private static void _OnDestroy() private static void _OnDestroy()
{ {
//Console.WriteLine("OnCreate"); //Console.WriteLine("OnCreate");
_context = new UIContext(); _context = new UIContext();
} }
[HarmonyPatch(typeof(UISaveGameWindow), "OnSaveClick"), HarmonyReversePatch] [HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow.OnSaveClick)), HarmonyReversePatch]
private static void OSaveGameAs(this UISaveGameWindow ui, int data) { } private static void OSaveGameAs(this UISaveGameWindow ui, int data) { }
[HarmonyPatch(typeof(UISaveGameWindow), "CheckAndSetSaveButtonEnable"), HarmonyPostfix] [HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow.CheckAndSetSaveButtonEnable)), HarmonyPostfix]
private static void CheckAndSetSaveButtonEnable(UISaveGameWindow __instance) private static void CheckAndSetSaveButtonEnable(UISaveGameWindow __instance)
{ {
_OnOpen(__instance); _OnOpen(__instance);
@@ -61,37 +62,43 @@ static class PatchUISaveGame
public UISaveGameWindow Window; public UISaveGameWindow Window;
} }
[HarmonyPatch(typeof(UISaveGameWindow), "OnSaveClick"), HarmonyPrefix] [HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow.OnSaveClick)), HarmonyPrefix]
private static void OnSaveClick() private static void OnSaveClick()
{ {
PatchSave.UseCompressSave = true; PatchSave.UseCompressSave = true;
PatchSave.UseCommonSaveCompressionType();
} }
private static UIContext _context = new(); private static UIContext _context = new();
[HarmonyPatch(typeof(UISaveGameWindow), "_OnOpen"), HarmonyPostfix] [HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow._OnOpen)), HarmonyPostfix]
private static void _OnOpen(UISaveGameWindow __instance) private static void _OnOpen(UISaveGameWindow __instance)
{ {
if (_context.ButtonCompress) return; if (_context.ButtonCompress)
{
var dist = __instance.cancelButton.transform.localPosition.x - __instance.saveButton.transform.localPosition.x - ((RectTransform)__instance.cancelButton.transform).sizeDelta.x;
var cRectTrans = (RectTransform)_context.ButtonCompress.transform;
var localPos = __instance.saveButton.transform.localPosition;
cRectTrans.localPosition = new Vector3(localPos.x - dist - ((RectTransform)__instance.saveButton.transform).sizeDelta.x, localPos.y, localPos.z);
return;
}
RectTransform rtrans; RectTransform rtrans;
Vector3 pos; Vector3 pos;
_context.SaveButton = __instance.saveButton; _context.SaveButton = __instance.saveButton;
_context.SaveButtonText = __instance.saveButtonText; _context.SaveButtonText = __instance.saveButtonText;
_context.Window = __instance; _context.Window = __instance;
var gameObj = __instance.transform.Find("button-compress")?.gameObject; var gameObj = __instance.transform.Find("button-compress")?.gameObject;
var created = false; var isCreating = false;
var theParent = __instance.saveButton.transform.parent;
if (gameObj == null) if (gameObj == null)
{ {
gameObj = Object.Instantiate(__instance.saveButton.gameObject, __instance.saveButton.transform.parent); gameObj = Object.Instantiate(__instance.saveButton.gameObject, theParent);
created = true; isCreating = true;
} }
_context.ButtonCompress = gameObj.GetComponent<UIButton>(); _context.ButtonCompress = gameObj.GetComponent<UIButton>();
if (created) if (isCreating)
{ {
_context.ButtonCompress.gameObject.name = "button-compress"; _context.ButtonCompress.gameObject.name = "button-compress";
rtrans = (RectTransform)_context.ButtonCompress.transform;
pos = rtrans.anchoredPosition3D;
rtrans.anchoredPosition3D = new Vector3(pos.x - 180, pos.y, pos.z);
_context.ButtonCompress.button.image.color = new Color32(0xfc, 0x6f, 00, 0x77); _context.ButtonCompress.button.image.color = new Color32(0xfc, 0x6f, 00, 0x77);
var textTrans = _context.ButtonCompress.transform.Find("button-text"); var textTrans = _context.ButtonCompress.transform.Find("button-text");
_context.ButtonCompressText = textTrans.GetComponent<Text>(); _context.ButtonCompressText = textTrans.GetComponent<Text>();
@@ -106,102 +113,78 @@ static class PatchUISaveGame
localizer.translation = "Save with Compression".Translate(); localizer.translation = "Save with Compression".Translate();
} }
} }
var distance = __instance.cancelButton.transform.localPosition.x - __instance.saveButton.transform.localPosition.x - ((RectTransform)__instance.cancelButton.transform).sizeDelta.x;
rtrans = (RectTransform)_context.ButtonCompress.transform;
pos = __instance.saveButton.transform.localPosition;
rtrans.localPosition = new Vector3(pos.x - distance - ((RectTransform)__instance.saveButton.transform).sizeDelta.x, pos.y, pos.z);
created = false; isCreating = false;
gameObj = __instance.transform.Find("manual-save-type-combobox")?.gameObject; gameObj = __instance.transform.Find("manual-save-type-combobox")?.gameObject;
if (gameObj == null) if (gameObj == null)
{ {
gameObj = Object.Instantiate(UIRoot.instance.optionWindow.resolutionComp.transform.parent.gameObject, __instance.saveButton.transform.parent); gameObj = UI.MyComboBox.CreateComboBox("manual-save-type-combobox");
created = true; isCreating = true;
} }
_context.ManualSaveTypeComboBox = gameObj; _context.ManualSaveTypeComboBox = gameObj;
if (created)
if (isCreating)
{ {
gameObj.name = "manual-save-type-combobox"; var btnCompressTrans = (RectTransform)_context.ButtonCompress.transform;
var text = AddText("Compression for manual saves", 14, "manual-save-type-combobox-text");
rtrans = text.rectTransform;
rtrans.SetParent(theParent, false);
pos = btnCompressTrans.localPosition;
rtrans.anchorMin = btnCompressTrans.anchorMin;
rtrans.anchorMax = btnCompressTrans.anchorMax;
rtrans.pivot = btnCompressTrans.pivot;
rtrans.localPosition = new Vector3(pos.x - 250f, pos.y + 45f, pos.z);
rtrans = (RectTransform)gameObj.transform; rtrans = (RectTransform)gameObj.transform;
var rtrans2 = (RectTransform)_context.ButtonCompress.transform; rtrans.SetParent(theParent, false);
pos = rtrans2.anchoredPosition3D; rtrans.anchorMin = btnCompressTrans.anchorMin;
rtrans.anchorMin = rtrans2.anchorMin; rtrans.anchorMax = btnCompressTrans.anchorMax;
rtrans.anchorMax = rtrans2.anchorMax; rtrans.pivot = btnCompressTrans.pivot;
rtrans.pivot = rtrans2.pivot; text.UpdateGeometry();
rtrans.anchoredPosition3D = new Vector3(pos.x + 100, pos.y + 45, pos.z); rtrans.localPosition = new Vector3(pos.x - 50f, pos.y + 45f, pos.z);
var cbctrl = rtrans.transform.Find("ComboBox"); var cb = rtrans.GetComponent<MyComboBox>();
var content = cbctrl.Find("Dropdown List ScrollBox")?.Find("Mask")?.Find("Content Panel"); cb.WithItems("Store".Translate(), "LZ4", "Zstd").WithIndex((int)PatchSave.CompressionTypeForSaves).WithOnSelChanged((idx) =>
if (content != null)
{ {
for (var i = content.childCount - 1; i >= 0; i--) PatchSave.CompressionTypeForSaves = (CompressionType)idx;
{
var theTrans = content.GetChild(i);
if (theTrans.name == "Item Button(Clone)")
{
Object.Destroy(theTrans.gameObject);
}
}
}
var cb = cbctrl.GetComponent<UIComboBox>();
cb.onSubmit.RemoveAllListeners();
cb.onItemIndexChange.RemoveAllListeners();
cb.Items = ["Store".Translate(), "LZ4", "Zstd"];
cb.itemIndex = (int)PatchSave.CompressionTypeForSaves;
cb.onItemIndexChange.AddListener(()=>
{
PatchSave.CompressionTypeForSaves = (CompressionType)cb.itemIndex;
PatchSave.CompressionTypeForSavesConfig.Value = CompressSave.StringFromCompresstionType(PatchSave.CompressionTypeForSaves); PatchSave.CompressionTypeForSavesConfig.Value = CompressSave.StringFromCompresstionType(PatchSave.CompressionTypeForSaves);
}); });
rtrans = (RectTransform)cb.transform;
pos = rtrans.anchoredPosition3D;
rtrans.anchoredPosition3D = new Vector3(pos.x - 50, pos.y, pos.z);
var size = rtrans.sizeDelta;
rtrans.sizeDelta = new Vector2(150f, size.y);
var txt = gameObj.GetComponent<Text>();
txt.text = "Compression for manual saves".Translate();
var localizer = gameObj.GetComponent<Localizer>();
if (localizer != null)
{
localizer.stringKey = "Compression for manual saves";
localizer.translation = "Compression for manual saves".Translate();
}
} }
created = false; isCreating = false;
gameObj = __instance.transform.Find("auto-save-type-combobox")?.gameObject; gameObj = __instance.transform.Find("auto-save-type-combobox")?.gameObject;
if (gameObj == null) if (gameObj == null)
{ {
gameObj = Object.Instantiate(UIRoot.instance.optionWindow.resolutionComp.transform.parent.gameObject, __instance.saveButton.transform.parent); gameObj = UI.MyComboBox.CreateComboBox("auto-save-type-combobox");
created = true; isCreating = true;
} }
_context.AutoSaveTypeComboBox = gameObj; _context.AutoSaveTypeComboBox = gameObj;
if (created) if (isCreating)
{ {
gameObj.name = "auto-save-type-combobox"; var btnCompressTrans = (RectTransform)_context.ButtonCompress.transform;
var text = AddText("Compression for auto saves", 14, "auto-save-type-combobox-text");
rtrans = text.rectTransform;
rtrans.SetParent(theParent, false);
pos = btnCompressTrans.localPosition;
rtrans.anchorMin = btnCompressTrans.anchorMin;
rtrans.anchorMax = btnCompressTrans.anchorMax;
rtrans.pivot = btnCompressTrans.pivot;
rtrans.localPosition = new Vector3(pos.x + 160f, pos.y + 45f, pos.z);
rtrans = (RectTransform)gameObj.transform; rtrans = (RectTransform)gameObj.transform;
var rtrans2 = (RectTransform)_context.ButtonCompress.transform; rtrans.SetParent(theParent, false);
pos = rtrans2.anchoredPosition3D; rtrans.anchorMin = btnCompressTrans.anchorMin;
rtrans.anchorMin = rtrans2.anchorMin; rtrans.anchorMax = btnCompressTrans.anchorMax;
rtrans.anchorMax = rtrans2.anchorMax; rtrans.pivot = btnCompressTrans.pivot;
rtrans.pivot = rtrans2.pivot; rtrans.localPosition = new Vector3(pos.x + 360f, pos.y + 45f, pos.z);
rtrans.anchoredPosition3D = new Vector3(pos.x + 510, pos.y + 45, pos.z); var cb = rtrans.GetComponent<MyComboBox>();
var cbctrl = rtrans.transform.Find("ComboBox"); cb.WithItems(["已停用".Translate(), "Store".Translate(), "LZ4", "Zstd"]).WithIndex(PatchSave.EnableForAutoSaves.Value ? (int)PatchSave.CompressionTypeForAutoSaves + 1 : 0)
var content = cbctrl.Find("Dropdown List ScrollBox")?.Find("Mask")?.Find("Content Panel"); .WithOnSelChanged((idx) =>
if (content != null)
{ {
for (var i = content.childCount - 1; i >= 0; i--)
{
var theTrans = content.GetChild(i);
if (theTrans.name == "Item Button(Clone)")
{
Object.Destroy(theTrans.gameObject);
}
}
}
var cb = cbctrl.GetComponent<UIComboBox>();
cb.onSubmit.RemoveAllListeners();
cb.onItemIndexChange.RemoveAllListeners();
cb.Items = ["已停用".Translate(), "Store".Translate(), "LZ4", "Zstd"];
cb.itemIndex = PatchSave.EnableForAutoSaves.Value ? (int)PatchSave.CompressionTypeForAutoSaves + 1 : 0;
cb.onItemIndexChange.AddListener(() =>
{
var idx = cb.itemIndex;
if (idx == 0) if (idx == 0)
{ {
PatchSave.EnableForAutoSaves.Value = false; PatchSave.EnableForAutoSaves.Value = false;
@@ -213,19 +196,6 @@ static class PatchUISaveGame
PatchSave.CompressionTypeForAutoSavesConfig.Value = CompressSave.StringFromCompresstionType(PatchSave.CompressionTypeForAutoSaves); PatchSave.CompressionTypeForAutoSavesConfig.Value = CompressSave.StringFromCompresstionType(PatchSave.CompressionTypeForAutoSaves);
} }
}); });
rtrans = (RectTransform)cb.transform;
pos = rtrans.anchoredPosition3D;
rtrans.anchoredPosition3D = new Vector3(pos.x - 50, pos.y, pos.z);
var size = rtrans.sizeDelta;
rtrans.sizeDelta = new Vector2(150f, size.y);
var txt = gameObj.GetComponent<Text>();
txt.text = "Compression for auto saves".Translate();
var localizer = gameObj.GetComponent<Localizer>();
if (localizer != null)
{
localizer.stringKey = "Compression for auto saves";
localizer.translation = "Compression for auto saves".Translate();
}
} }
} }
@@ -234,4 +204,16 @@ static class PatchUISaveGame
PatchSave.UseCompressSave = false; PatchSave.UseCompressSave = false;
_context.Window.OSaveGameAs(data); _context.Window.OSaveGameAs(data);
} }
public static Text AddText(string label, int fontSize = 14, string objName = "label")
{
var txt = Object.Instantiate(UIRoot.instance.uiGame.assemblerWindow.stateText);
txt.gameObject.name = objName;
txt.text = label.Translate();
txt.color = new Color(1f, 1f, 1f, 0.4f);
txt.alignment = TextAnchor.MiddleLeft;
txt.fontSize = fontSize;
txt.rectTransform.sizeDelta = new Vector2(txt.preferredWidth + 8f, txt.preferredHeight + 8f);
return txt;
}
} }

View File

@@ -13,7 +13,7 @@ public static class SaveUtil
{ {
Major = 0, Major = 0,
Minor = 10, Minor = 10,
Release = 28, Release = 34,
}; };
private static string UnzipToFile(DecompressionStream lzStream, string fullPath) private static string UnzipToFile(DecompressionStream lzStream, string fullPath)

View File

@@ -0,0 +1,156 @@
using System;
using System.Linq;
using BepInEx.Configuration;
using UnityEngine;
using UnityEngine.UI;
namespace CompressSave.UI;
public class MyComboBox : MonoBehaviour
{
private RectTransform _rectTrans;
private UIComboBox _comboBox;
public Action<int> OnSelChanged;
private static GameObject _baseObject;
public static void InitBaseObject()
{
if (_baseObject) return;
var fontSource = UIRoot.instance.uiGame.buildMenu.uxFacilityCheck.transform.Find("text")?.GetComponent<Text>();
var go = Instantiate(UIRoot.instance.optionWindow.resolutionComp.gameObject);
go.name = "my-combobox";
go.SetActive(false);
var rect = (RectTransform)go.transform;
var cbctrl = rect.GetComponent<UIComboBox>();
foreach (var button in cbctrl.ItemButtons)
{
Destroy(button.gameObject);
}
cbctrl.Items.Clear();
cbctrl.ItemButtons.Clear();
if (fontSource)
{
var txtComp = cbctrl.m_ListItemRes.GetComponentInChildren<Text>();
if (txtComp)
{
txtComp.font = fontSource.font;
txtComp.fontSize = fontSource.fontSize;
txtComp.fontStyle = fontSource.fontStyle;
}
txtComp = rect.Find("Main Button/Text")?.GetComponent<Text>();
if (txtComp)
{
txtComp.font = fontSource.font;
txtComp.fontSize = fontSource.fontSize;
txtComp.fontStyle = fontSource.fontStyle;
}
}
cbctrl.onSubmit.RemoveAllListeners();
cbctrl.onItemIndexChange.RemoveAllListeners();
_baseObject = go;
}
public static GameObject CreateComboBox(string name)
{
if (_baseObject == null) InitBaseObject();
var gameObject = Instantiate(_baseObject);
gameObject.name = name;
gameObject.SetActive(true);
var cb = gameObject.AddComponent<MyComboBox>();
cb._rectTrans = (RectTransform)gameObject.transform;
var box = cb._rectTrans.GetComponent<UIComboBox>();
cb._comboBox = box;
box.onItemIndexChange.AddListener(() => { cb.OnSelChanged?.Invoke(box.itemIndex); });
return gameObject;
}
protected void OnDestroy()
{
_config.SettingChanged -= _configChanged;
}
public void SetFontSize(int size)
{
_comboBox.ItemButtons.ForEach(b => b.GetComponentInChildren<Text>().fontSize = size);
_comboBox.m_ListItemRes.GetComponentInChildren<Text>().fontSize = size;
var txtComp = _comboBox.transform.Find("Main Button")?.GetComponentInChildren<Text>();
if (txtComp) txtComp.fontSize = size;
}
public void SetItems(params string[] items)
{
_comboBox.Items = [.. items.Select(s => s.Translate())];
_comboBox.StartItemIndex = 0;
_comboBox.DropDownCount = Math.Min(items.Length, 8);
}
public void SetIndex(int index) => _comboBox.itemIndex = index;
public void SetSize(float width, float height)
{
var rtrans = (RectTransform)_comboBox.transform;
rtrans.sizeDelta = new Vector2(width > 0f ? width : rtrans.sizeDelta.x, height > 0f ? height : rtrans.sizeDelta.y);
_rectTrans.sizeDelta = new Vector2(rtrans.localPosition.x + rtrans.sizeDelta.x, _rectTrans.sizeDelta.y);
}
public void AddOnSelChanged(Action<int> action) => OnSelChanged += action;
private EventHandler _configChanged;
private Action<int> _selChanged;
private ConfigEntry<int> _config;
public void SetConfigEntry(ConfigEntry<int> config)
{
if (_selChanged != null) OnSelChanged -= _selChanged;
if (_configChanged != null) config.SettingChanged -= _configChanged;
_comboBox.itemIndex = config.Value;
_config = config;
_selChanged = value => config.Value = value;
OnSelChanged += _selChanged;
_configChanged = (_, _) => SetIndex(config.Value);
config.SettingChanged += _configChanged;
}
public MyComboBox WithFontSize(int size)
{
SetFontSize(size);
return this;
}
public MyComboBox WithItems(params string[] items)
{
SetItems(items);
return this;
}
public MyComboBox WithIndex(int index)
{
SetIndex(index);
return this;
}
public MyComboBox WithSize(float width, float height)
{
SetSize(width, height);
return this;
}
public MyComboBox WithOnSelChanged(params Action<int>[] action)
{
foreach (var act in action)
AddOnSelChanged(act);
return this;
}
public MyComboBox WithConfigEntry(ConfigEntry<int> config)
{
SetConfigEntry(config);
return this;
}
public float Width => _rectTrans.sizeDelta.x;
public float Height => _rectTrans.sizeDelta.y;
}

View File

@@ -1,6 +1,6 @@
{ {
"name": "CompressSave", "name": "CompressSave",
"version_number": "1.3.7", "version_number": "1.3.8",
"website_url": "https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave", "website_url": "https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave",
"description": "Compress game saves to reduce space use and boost save speed / 压缩游戏存档以降低空间使用并提升保存速度", "description": "Compress game saves to reduce space use and boost save speed / 压缩游戏存档以降低空间使用并提升保存速度",
"dependencies": ["xiaoye97-BepInEx-5.4.17"] "dependencies": ["xiaoye97-BepInEx-5.4.17"]

View File

@@ -385,7 +385,7 @@ namespace XianTu.Scripts.DataController
break; break;
} }
buildToolBlueprintPaste.UpdatePreviewModels(_actionBuild.model); buildToolBlueprintPaste.UpdatePreviewModels(_actionBuild.model);
buildToolBlueprintPaste.ErrorGridClustering(); buildToolBlueprintPaste.TranslateErrorType(false);
} }
} }

View File

@@ -19,6 +19,7 @@
<!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" /> --> <!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" /> -->
<!-- <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.*" /> --> <!-- <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.*" /> -->
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath> <HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>