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

Compare commits

..

3 Commits

Author SHA1 Message Date
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
11 changed files with 390 additions and 276 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
* 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)).
## Changelog
### 1.3.6
* Support for using subfolder in save filepath (only MODs are doing this currently).
* 1.3.8
* Support for game version 0.10.34.
### 1.3.5
* Fix a crash issue on choosing language other than English and Chinese.
* 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)).
### 1.3.4
* Support for game version 0.10.28.20759.
* 1.3.6
* Support for using subfolder in save filepath (only MODs are doing this currently).
### 1.3.3
* Fix a display issue on combobox of compression type.
* 1.3.5
* Fix a crash issue on choosing language other than English and Chinese.
### 1.3.2
* Add config UI on Save Game dialog, to set compression types.
* Change button text to `Save (Compress)` for better understanding.
* 1.3.4
* Support for game version 0.10.28.20759.
### 1.3.1
* Add config to disable feature for auto saves.
* Fix bug that first save after game start is always compressed in Zstd.
* 1.3.3
* Fix a display issue on combobox of compression type.
### 1.3.0
* 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.
* 1.3.2
* Add config UI on Save Game dialog, to set compression types. * Change button text to `Save (Compress)` for better understanding.
* 1.3.1
* Add config to disable feature for auto saves. * Fix bug that first save after game start is always compressed in Zstd.
* 1.3.0
* 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.
<details>
<summary>Older versions</summary>
### 1.2.2
* Fix #4, a bug caused by non-ASCII UTF-8 characters.
* Remove use of Harmony.UnpatchAll() to avoid warnings in BepInEx log.
* 1.2.2
* Fix #4, a bug caused by non-ASCII UTF-8 characters. * Remove use of Harmony.UnpatchAll() to avoid warnings in BepInEx log.
### 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()`.
* 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.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()`. * 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
* 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.
* 1.2.0
* 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.
### 1.1.14
* Fix Sandbox info on Save/Load Panel.
* Fix DLL version info.
* 1.1.14
* Fix Sandbox info on Save/Load Panel. * 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
* Match game version 0.9.25.12007.
### 1.1.12
* 1.1.11
* Fix 1.1.10 package issue.
* Match game version 0.9.25.12007.
* 1.1.10
* Fix 1.1.8 Archive corruption with DIY System, corrupted archives can be fixed by using \[Fix118\] mod
### 1.1.11
Fix118: <https://github.com/bluedoom/DSP_Mod/blob/master/Fix118>
* Fix 1.1.10 package issue.
* 1.1.9
* CompressSave is temporarily disabled due to some error with the DIY system.
### 1.1.10
* 1.1.8
* Match game version 0.9.24.11029
* Fix 1.1.8 Archive corruption with DIY System, corrupted archives can be fixed by using \[Fix118\] mod
* 1.1.7
* Fix incorrect data on statistic panel. * Improve performance.
Fix118: https://github.com/bluedoom/DSP_Mod/blob/master/Fix118
* 1.1.6
* fix memory leak
### 1.1.9
* 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.
* CompressSave is temporarily disabled due to some error with the DIY system.
* 1.1.4 (Game Version 0.8.19)
* Match game version 0.8.19.
### 1.1.8
* 1.1.3 (2021/05/29) (Game Version 0.7.18)
* Match game version 0.7.18. * Fix memory leak.
* Match game version 0.9.24.11029
* 1.1.2 (2021/03/24) (Game Version 0.6.17)
* Handle lz4 library missing Error
### 1.1.7
* 1.1.1 (2021/03/17) (Game Version 0.6.17)
* Fix Load Error
* Fix incorrect data on statistic panel.
* Improve performance.
### 1.1.6
* fix memory leak
### 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.
### 1.1.4 (Game Version 0.8.19)
* Match game version 0.8.19.
### 1.1.3 (2021/05/29) (Game Version 0.7.18)
* Match game version 0.7.18.
* Fix memory leak.
### 1.1.2 (2021/03/24) (Game Version 0.6.17)
* Handle lz4 library missing Error
### 1.1.1 (2021/03/17) (Game Version 0.6.17)
* Fix Load Error
### 1.1.0 (2021/03/17) (Game Version 0.6.17)
* Add UI button
* 1.1.0 (2021/03/17) (Game Version 0.6.17)
* Add UI button
</details>
</details>
<details>
<summary>中文读我</summary>
## 更新日志
### 1.3.7
* 移除使用MonoMod.Util加载dll导入函数以使MOD与HarmonyX 2.13.0兼容(尽管此改动尚未合并。[在此](https://github.com/BepInEx/BepInEx/pull/902)查看合并请求)
* 1.3.8
* 支持游戏版本 0.10.34
### 1.3.6
* 支持在存档路径中使用子文件夹(目前只有MOD会这么干)。
* 1.3.7
* 移除使用MonoMod.Util加载dll导入函数以使MOD与HarmonyX 2.13.0兼容(尽管此改动尚未合并。[在此](https://github.com/BepInEx/BepInEx/pull/902)查看合并请求)。
### 1.3.5
* 修复了选择英文和中文以外的语言时的崩溃问题
* 1.3.6
* 支持在存档路径中使用子文件夹(目前只有MOD会这么干)
### 1.3.4
* 支持游戏版本 0.10.28.20759
* 1.3.5
* 修复了选择英文和中文以外的语言时的崩溃问题
### 1.3.3
* 修复压缩类型下拉框显示问题
* 1.3.4
* 支持游戏版本 0.10.28.20759
### 1.3.2
* 在保存面板上增加设置压缩方式的UI
* 将按钮文本改为`压缩保存`以区分功能。
* 1.3.3
* 修复压缩类型下拉框显示问题
### 1.3.1
* 增加在自动存档中禁用压缩的设置项
* 修复一个导致游戏开始后第一次保存总是使用Zstd压缩的bug。
* 1.3.2
* 在保存面板上增加设置压缩方式的UI。 * 将按钮文本改为`压缩保存`以区分功能
### 1.3.0
* 分离手动存档和自动存档的设置项
* 现在在自动存档设置压缩类型为`存储`也可以获得速度提升,手动存档也可以在使用新的`保存`按钮后获得速度提升。
+ 为此增加了`nonewrap.dll`
* 更新`LZ4``Zstd`库到最新版本。
* `lz4wrap.dll``zstdwrap.dll`使用`-O3`编译而不是`-Os`,速度略有提升但体积变大。
* 1.3.1
* 增加在自动存档中禁用压缩的设置项。 * 修复一个导致游戏开始后第一次保存总是使用Zstd压缩的bug
* 1.3.0
* 分离手动存档和自动存档的设置项。 * 现在在自动存档设置压缩类型为`存储`也可以获得速度提升,手动存档也可以在使用新的`保存`按钮后获得速度提升。 * 为此增加了`nonewrap.dll`* 更新`LZ4``Zstd`库到最新版本。 * `lz4wrap.dll``zstdwrap.dll`使用`-O3`编译而不是`-Os`,速度略有提升但体积变大。
<details>
<summary>Older versions</summary>
### 1.2.2
* 修复 #4一个导致非ASCII UTF-8字符导致的bug。
* 移除使用Harmony.UnpatchAll()以避免在BepInEx日志中出现警告。
* 1.2.2
* 修复 #4一个导致非ASCII UTF-8字符导致的bug。 * 移除使用Harmony.UnpatchAll()以避免在BepInEx日志中出现警告。
### 1.2.1
* 简化代码以在存档读取面板上显示压缩类型和`解压`按钮使得CompressSave与其他MOD(如GalacticScale)兼容,因为它们都覆盖了`UILoadGameWindow::OnSelectedChange()`
* 为zstd添加了压缩等级-5到-1现在它比lz4(实际上是lz4frame)表现更好了:
* -5比lz4更快但压缩比略有提升。
* -1和lz4几乎一样快但压缩比更高。
* 由于r2modman UI的bug压缩等级的设置项不再限制范围。
* 将本地的wrapper DLL移动到`x64`目录。
* 1.2.1
* 简化代码以在存档读取面板上显示压缩类型和`解压`按钮使得CompressSave与其他MOD(如GalacticScale)兼容,因为它们都覆盖了`UILoadGameWindow::OnSelectedChange()` * 为zstd添加了压缩等级-5到-1现在它比lz4(实际上是lz4frame)表现更好了: * -5比lz4更快但压缩比略有提升。 * -1和lz4几乎一样快但压缩比更高。 * 由于r2modman UI的bug压缩等级的设置项不再限制范围。 * 将本地的wrapper DLL移动到`x64`目录。
</details>
</details>

View File

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

View File

@@ -4,7 +4,7 @@
<AssemblyName>CompressSave</AssemblyName>
<BepInExPluginGuid>org.soardev.compresssave</BepInExPluginGuid>
<Description>DSP MOD - CompressSave</Description>
<Version>1.3.7</Version>
<Version>1.3.8</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<TargetFramework>net472</TargetFramework>
@@ -14,9 +14,9 @@
<ItemGroup>
<PackageReference Include="BepInEx.Core" Version="5.*" />
<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="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
<PackageReference Include="UnityEngine.Modules" Version="2022.3.53" IncludeAssets="compile" />
</ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
@@ -27,6 +27,15 @@
</Reference>
</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'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
</ItemGroup>

View File

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

View File

@@ -1,3 +1,4 @@
using CompressSave.UI;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
@@ -18,7 +19,7 @@ static class PatchUISaveGame
_OnDestroy();
}
[HarmonyPatch(typeof(UISaveGameWindow), "OnSelectedChange"), HarmonyPostfix]
[HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow.OnSelectedChange)), HarmonyPostfix]
private static void OnSelectedChange(UISaveGameWindow __instance)
{
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()
{
//Console.WriteLine("OnCreate");
_context = new UIContext();
}
[HarmonyPatch(typeof(UISaveGameWindow), "OnSaveClick"), HarmonyReversePatch]
[HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow.OnSaveClick)), HarmonyReversePatch]
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)
{
_OnOpen(__instance);
@@ -61,37 +62,43 @@ static class PatchUISaveGame
public UISaveGameWindow Window;
}
[HarmonyPatch(typeof(UISaveGameWindow), "OnSaveClick"), HarmonyPrefix]
[HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow.OnSaveClick)), HarmonyPrefix]
private static void OnSaveClick()
{
PatchSave.UseCompressSave = true;
PatchSave.UseCommonSaveCompressionType();
}
private static UIContext _context = new();
[HarmonyPatch(typeof(UISaveGameWindow), "_OnOpen"), HarmonyPostfix]
[HarmonyPatch(typeof(UISaveGameWindow), nameof(UISaveGameWindow._OnOpen)), HarmonyPostfix]
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;
Vector3 pos;
_context.SaveButton = __instance.saveButton;
_context.SaveButtonText = __instance.saveButtonText;
_context.Window = __instance;
var gameObj = __instance.transform.Find("button-compress")?.gameObject;
var created = false;
var isCreating = false;
var theParent = __instance.saveButton.transform.parent;
if (gameObj == null)
{
gameObj = Object.Instantiate(__instance.saveButton.gameObject, __instance.saveButton.transform.parent);
created = true;
gameObj = Object.Instantiate(__instance.saveButton.gameObject, theParent);
isCreating = true;
}
_context.ButtonCompress = gameObj.GetComponent<UIButton>();
if (created)
if (isCreating)
{
_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);
var textTrans = _context.ButtonCompress.transform.Find("button-text");
_context.ButtonCompressText = textTrans.GetComponent<Text>();
@@ -106,102 +113,78 @@ static class PatchUISaveGame
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;
if (gameObj == null)
{
gameObj = Object.Instantiate(UIRoot.instance.optionWindow.resolutionComp.transform.parent.gameObject, __instance.saveButton.transform.parent);
created = true;
gameObj = UI.MyComboBox.CreateComboBox("manual-save-type-combobox");
isCreating = true;
}
_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;
var rtrans2 = (RectTransform)_context.ButtonCompress.transform;
pos = rtrans2.anchoredPosition3D;
rtrans.anchorMin = rtrans2.anchorMin;
rtrans.anchorMax = rtrans2.anchorMax;
rtrans.pivot = rtrans2.pivot;
rtrans.anchoredPosition3D = new Vector3(pos.x + 100, pos.y + 45, pos.z);
var cbctrl = rtrans.transform.Find("ComboBox");
var content = cbctrl.Find("Dropdown List ScrollBox")?.Find("Mask")?.Find("Content Panel");
if (content != null)
rtrans.SetParent(theParent, false);
rtrans.anchorMin = btnCompressTrans.anchorMin;
rtrans.anchorMax = btnCompressTrans.anchorMax;
rtrans.pivot = btnCompressTrans.pivot;
text.UpdateGeometry();
rtrans.localPosition = new Vector3(pos.x - 50f, pos.y + 45f, pos.z);
var cb = rtrans.GetComponent<MyComboBox>();
cb.WithItems("Store".Translate(), "LZ4", "Zstd").WithIndex((int)PatchSave.CompressionTypeForSaves).WithOnSelChanged((idx) =>
{
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 = ["Store".Translate(), "LZ4", "Zstd"];
cb.itemIndex = (int)PatchSave.CompressionTypeForSaves;
cb.onItemIndexChange.AddListener(()=>
{
PatchSave.CompressionTypeForSaves = (CompressionType)cb.itemIndex;
PatchSave.CompressionTypeForSaves = (CompressionType)idx;
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;
if (gameObj == null)
{
gameObj = Object.Instantiate(UIRoot.instance.optionWindow.resolutionComp.transform.parent.gameObject, __instance.saveButton.transform.parent);
created = true;
gameObj = UI.MyComboBox.CreateComboBox("auto-save-type-combobox");
isCreating = true;
}
_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;
var rtrans2 = (RectTransform)_context.ButtonCompress.transform;
pos = rtrans2.anchoredPosition3D;
rtrans.anchorMin = rtrans2.anchorMin;
rtrans.anchorMax = rtrans2.anchorMax;
rtrans.pivot = rtrans2.pivot;
rtrans.anchoredPosition3D = new Vector3(pos.x + 510, pos.y + 45, pos.z);
var cbctrl = rtrans.transform.Find("ComboBox");
var content = cbctrl.Find("Dropdown List ScrollBox")?.Find("Mask")?.Find("Content Panel");
if (content != null)
rtrans.SetParent(theParent, false);
rtrans.anchorMin = btnCompressTrans.anchorMin;
rtrans.anchorMax = btnCompressTrans.anchorMax;
rtrans.pivot = btnCompressTrans.pivot;
rtrans.localPosition = new Vector3(pos.x + 360f, pos.y + 45f, pos.z);
var cb = rtrans.GetComponent<MyComboBox>();
cb.WithItems(["已停用".Translate(), "Store".Translate(), "LZ4", "Zstd"]).WithIndex(PatchSave.EnableForAutoSaves.Value ? (int)PatchSave.CompressionTypeForAutoSaves + 1 : 0)
.WithOnSelChanged((idx) =>
{
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)
{
PatchSave.EnableForAutoSaves.Value = false;
@@ -213,19 +196,6 @@ static class PatchUISaveGame
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;
_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,
Minor = 10,
Release = 28,
Release = 34,
};
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",
"version_number": "1.3.7",
"version_number": "1.3.8",
"website_url": "https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave",
"description": "Compress game saves to reduce space use and boost save speed / 压缩游戏存档以降低空间使用并提升保存速度",
"dependencies": ["xiaoye97-BepInEx-5.4.17"]

View File

@@ -16,9 +16,10 @@
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<PackageReference Include="UnityEngine.Modules" Version="2022.3.53" IncludeAssets="compile" />
<!--<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />-->
<!--<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.*" />-->
<!-- <PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" /> -->
<!-- <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.*" /> -->
</ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>