Skip to content

Commit 239c9ee

Browse files
authored
Add SBPR_Fix_ResourceUnloadOptimizations (#38)
1 parent 7918f71 commit 239c9ee

File tree

7 files changed

+196
-7
lines changed

7 files changed

+196
-7
lines changed

IllusionFixes.sln

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KKS_Fix_PersonalityCorrecto
299299
EndProject
300300
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Core_Fix_PersonalityCorrector", "src\Core_Fix_PersonalityCorrector\Core_Fix_PersonalityCorrector.shproj", "{7A9F7BD1-FC29-4D40-BE21-66BBA1845D35}"
301301
EndProject
302+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SBPR_Fix_ResourceUnloadOptimizations", "src\SBPR_Fix_ResourceUnloadOptimizations\SBPR_Fix_ResourceUnloadOptimizations.csproj", "{09D5D602-4CFD-43C3-AD7E-58E5072E8127}"
303+
EndProject
302304
Global
303305
GlobalSection(SharedMSBuildProjectFiles) = preSolution
304306
src\Common\Common.projitems*{00e09fd0-9862-41b3-bd2c-7094a16c97f7}*SharedItemsImports = 4
@@ -312,6 +314,8 @@ Global
312314
src\Common\Common.projitems*{08a43f46-904c-4add-86cf-7170f1b1f087}*SharedItemsImports = 4
313315
src\Common\Common.projitems*{091fd8bf-29a8-4d03-93b1-4ceb8753315e}*SharedItemsImports = 4
314316
src\Core_Fix_WetAccessories\Core_Fix_WetAccessories.projitems*{091fd8bf-29a8-4d03-93b1-4ceb8753315e}*SharedItemsImports = 4
317+
src\Common\Common.projitems*{09d5d602-4cfd-43c3-ad7e-58e5072e8127}*SharedItemsImports = 4
318+
src\Core_Fix_ResourceUnloadOptimizations\Core_Fix_ResourceUnloadOptimizations.projitems*{09d5d602-4cfd-43c3-ad7e-58e5072e8127}*SharedItemsImports = 4
315319
src\Common\Common.projitems*{09ebe942-19bb-445a-a1d4-06f185d7f518}*SharedItemsImports = 4
316320
src\Common\Common.projitems*{0c5a556c-af80-4562-ab56-c103e48ddce9}*SharedItemsImports = 4
317321
src\Core_Fix_ModdedHeadEyeliner\Core_Fix_ModdedHeadEyeliner.projitems*{14973826-75a9-4194-a9ec-2a1de3d20c36}*SharedItemsImports = 13
@@ -900,6 +904,10 @@ Global
900904
{1F49B69E-9C3C-4A0F-B0EB-28A8E907E6D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
901905
{1F49B69E-9C3C-4A0F-B0EB-28A8E907E6D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
902906
{1F49B69E-9C3C-4A0F-B0EB-28A8E907E6D6}.Release|Any CPU.Build.0 = Release|Any CPU
907+
{09D5D602-4CFD-43C3-AD7E-58E5072E8127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
908+
{09D5D602-4CFD-43C3-AD7E-58E5072E8127}.Debug|Any CPU.Build.0 = Debug|Any CPU
909+
{09D5D602-4CFD-43C3-AD7E-58E5072E8127}.Release|Any CPU.ActiveCfg = Release|Any CPU
910+
{09D5D602-4CFD-43C3-AD7E-58E5072E8127}.Release|Any CPU.Build.0 = Release|Any CPU
903911
EndGlobalSection
904912
GlobalSection(SolutionProperties) = preSolution
905913
HideSolutionNode = FALSE
@@ -1012,6 +1020,7 @@ Global
10121020
{DB6D687E-C491-44EA-8FC8-A96D3C62D2CA} = {D3136A19-617D-4426-827A-00A51D84925F}
10131021
{1F49B69E-9C3C-4A0F-B0EB-28A8E907E6D6} = {40715440-0FF3-47D1-BC1F-96AC7FDAF26E}
10141022
{7A9F7BD1-FC29-4D40-BE21-66BBA1845D35} = {40715440-0FF3-47D1-BC1F-96AC7FDAF26E}
1023+
{09D5D602-4CFD-43C3-AD7E-58E5072E8127} = {47CA3E45-1672-4D71-ABD2-8621D4C74003}
10151024
EndGlobalSection
10161025
GlobalSection(ExtensibilityGlobals) = postSolution
10171026
SolutionGuid = {D3F10C8B-FD6C-43DA-94B4-1D9688BBE11B}

src/Common/Constants.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ internal static class Constants
4848
internal const string GameProcessName = "KoikatsuSunshine";
4949
internal const string StudioProcessName = "CharaStudio";
5050
internal const string VRProcessName = "KoikatsuSunshine_VR";
51+
#elif SBPR
52+
internal static bool InsideStudio => false;
53+
internal const string GameProcessName = "SexyBeachPR_64";
54+
internal const string GameProcessName32bit = "SexyBeachPR_32";
5155
#endif
5256
}
5357
}

src/Common/Utilities.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,18 @@ internal static class Utilities
1010
public const string ConfigSectionFixes = "Bug Fixes";
1111
public const string ConfigSectionTweaks = "Tweaks";
1212

13-
public static bool InsideStudio { get; } = Application.productName == "CharaStudio" || Application.productName == "StudioNEOV2";
13+
public static bool InsideStudio { get; } =
14+
#if !SBPR
15+
Application.productName == "CharaStudio" || Application.productName == "StudioNEOV2";
16+
#else
17+
false;
18+
#endif
1419

15-
public static bool InsideKoikatsuParty { get; } = Application.productName == "Koikatsu Party";
20+
public static bool InsideKoikatsuParty { get; } =
21+
#if !SBPR
22+
Application.productName == "Koikatsu Party";
23+
#else
24+
false;
25+
#endif
1626
}
1727
}

src/Core_Fix_ResourceUnloadOptimizations/Core.ResourceUnloadOptimizations.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,17 @@ public partial class ResourceUnloadOptimizations
2828
public static ConfigEntry<bool> OptimizeMemoryUsage { get; private set; }
2929
public static ConfigEntry<int> PercentMemoryThreshold { get; private set; }
3030
public static ConfigEntry<int> PercentMemoryThresholdDuringLoad { get; private set; }
31-
31+
3232
internal void Awake()
3333
{
3434
DisableUnload = Config.Bind(Utilities.ConfigSectionTweaks, "Disable Resource Unload", false, new ConfigDescription("Disables all resource unloading. Requires large amounts of RAM or will likely crash your game.", null, new ConfigurationManagerAttributes { IsAdvanced = true }));
3535
OptimizeMemoryUsage = Config.Bind(Utilities.ConfigSectionTweaks, "Optimize Memory Usage", true, new ConfigDescription("Use more memory (if available) in order to load the game faster and reduce random stutter."));
3636
PercentMemoryThreshold = Config.Bind(Utilities.ConfigSectionTweaks, "Optimize Memory Threshold", 75, new ConfigDescription("Minimum amount of memory to be used before resource unloading will run.", null, new ConfigurationManagerAttributes {IsAdvanced = true}));
37-
PercentMemoryThresholdDuringLoad = Config.Bind(Utilities.ConfigSectionTweaks, "Optimize Memory Threshold During Load", 65, new ConfigDescription("Minimum amount of memory to be used during load before resource unloading will run (should be lower than 'Percent Memory Threshold').", null, new ConfigurationManagerAttributes {IsAdvanced = true}));
37+
#if !SBPR
38+
PercentMemoryThresholdDuringLoad = Config.Bind(Utilities.ConfigSectionTweaks, "Optimize Memory Threshold During Load", 65, new ConfigDescription($"Minimum amount of memory to be used during load before resource unloading will run (should be lower than 'Optimize Memory Threshold').", null, new ConfigurationManagerAttributes {IsAdvanced = true}));
39+
#else
40+
PercentMemoryThresholdDuringLoad = Config.Bind(Utilities.ConfigSectionTweaks, "Optimize Memory Threshold During Load", 80, new ConfigDescription($"Minimum amount of memory to be used during load before resource unloading will run (should be higher than 'Optimize Memory Threshold').", null, new ConfigurationManagerAttributes { IsAdvanced = true }));
41+
#endif
3842
StartCoroutine(CleanupCo());
3943

4044
InstallHooks();
@@ -120,6 +124,14 @@ private static bool GetIsNowLoadingFade()
120124
return Manager.Scene.IsNowLoadingFade;
121125
#elif PH
122126
return true;
127+
#elif SBPR
128+
if (Constants.InsideStudio) return false;
129+
// SBPR main game loading detection is a bit more convoluted since large async loads
130+
// happen at during live game play
131+
return !Manager.Scene.IsInstance() || !Manager.Map.IsInstance() || !Manager.MapScene.IsInstance() ||
132+
Manager.Map.Instance.NowLoading || Manager.MapScene.Instance.MapSceneClass == null ||
133+
Manager.MapScene.Instance.MapSceneClass.IsNowLoading || Manager.Scene.Instance.sceneFade == null ||
134+
Manager.Scene.Instance.sceneFade.IsFadeNow;
123135
#else
124136
return !Manager.Scene.IsInstance() || Manager.Scene.Instance.IsNowLoadingFade;
125137
#endif
@@ -143,7 +155,7 @@ private static IEnumerator SceneLoadComplete()
143155
_sceneLoadedOrReset = true;
144156
}
145157

146-
private static class Hooks
158+
private static partial class Hooks
147159
{
148160
[HarmonyPrefix]
149161
[HarmonyPatch(typeof(GC), nameof(GC.Collect), new Type[0])]
@@ -164,12 +176,12 @@ public static AsyncOperation UnloadUnusedAssetsHook()
164176
return RunUnloadAssets();
165177
}
166178

167-
#if !EC
179+
#if !EC && !SBPR
168180
[HarmonyPrefix]
169181
[HarmonyPatch(typeof(Studio.Studio), nameof(Studio.Studio.LoadScene))]
170182
[HarmonyPatch(typeof(Studio.Studio), nameof(Studio.Studio.ImportScene))]
171183
[HarmonyPatch(typeof(Studio.Studio), nameof(Studio.Studio.InitScene))]
172-
#if !HS && !PH
184+
#if !HS && !PH && !SBPR
173185
[HarmonyPatch(typeof(Studio.Studio), nameof(Studio.Studio.LoadSceneCoroutine))]
174186
#endif
175187
public static void LoadScenePrefix()
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using BepInEx;
2+
using Common;
3+
using HarmonyLib;
4+
using System;
5+
using System.Collections;
6+
using UnityEngine;
7+
8+
namespace IllusionFixes
9+
{
10+
[BepInProcess(Constants.GameProcessName)]
11+
[BepInProcess(Constants.GameProcessName32bit)]
12+
[BepInPlugin(GUID, PluginName, Constants.PluginsVersion)]
13+
public partial class ResourceUnloadOptimizations : BaseUnityPlugin
14+
{
15+
public const string GUID = "SBPR_Fix_ResourceUnloadOptimizations";
16+
17+
private static Coroutine _currentCleanupAfterLoading = null;
18+
19+
private static IEnumerator CleanupAfterAsyncLoading()
20+
{
21+
yield return null;
22+
while (GetIsNowLoadingFade())
23+
{
24+
yield return null;
25+
}
26+
27+
// force a single unload once large load operation finishes
28+
while (_currentOperation != null && !_currentOperation.isDone)
29+
{
30+
yield return null;
31+
}
32+
_currentOperation = _originalUnload();
33+
yield return null;
34+
// force GC
35+
GC.Collect(GC.MaxGeneration);
36+
_currentCleanupAfterLoading = null;
37+
}
38+
39+
partial class Hooks
40+
{
41+
// deploy happens when:
42+
// - main game save is loaded
43+
// - Time of day changes
44+
// - entering main game map from another scene (h-scene, changing room, etc.)
45+
[HarmonyPostfix]
46+
[HarmonyPatch(typeof(SexyBeach.MapScene), nameof(SexyBeach.MapScene.Deploy))]
47+
public static void DeployPostfix(SexyBeach.MapScene __instance)
48+
{
49+
if (!OptimizeMemoryUsage.Value || __instance == null) return;
50+
if (_currentCleanupAfterLoading != null) __instance.StopCoroutine(_currentCleanupAfterLoading);
51+
_currentCleanupAfterLoading = __instance.StartCoroutine(CleanupAfterAsyncLoading());
52+
}
53+
54+
}
55+
}
56+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<OutputType>Library</OutputType>
8+
<AppDesignerFolder>Properties</AppDesignerFolder>
9+
<RootNamespace>IllusionFixes</RootNamespace>
10+
<AssemblyName>SBPR_Fix_ResourceUnloadOptimizations</AssemblyName>
11+
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
12+
<FileAlignment>512</FileAlignment>
13+
<Deterministic>true</Deterministic>
14+
<NuGetPackageImportStamp>
15+
</NuGetPackageImportStamp>
16+
<ProjectGuid>{09D5D602-4CFD-43C3-AD7E-58E5072E8127}</ProjectGuid>
17+
</PropertyGroup>
18+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
19+
<DebugSymbols>true</DebugSymbols>
20+
<DebugType>embedded</DebugType>
21+
<Optimize>false</Optimize>
22+
<OutputPath>..\..\bin\BepInEx\plugins\IllusionFixes\</OutputPath>
23+
<DefineConstants>TRACE;DEBUG;SBPR</DefineConstants>
24+
<ErrorReport>prompt</ErrorReport>
25+
<WarningLevel>4</WarningLevel>
26+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
27+
</PropertyGroup>
28+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
29+
<DebugType>embedded</DebugType>
30+
<Optimize>true</Optimize>
31+
<OutputPath>..\..\bin\BepInEx\plugins\IllusionFixes\</OutputPath>
32+
<DefineConstants>TRACE;SBPR</DefineConstants>
33+
<ErrorReport>prompt</ErrorReport>
34+
<WarningLevel>4</WarningLevel>
35+
<DebugSymbols>true</DebugSymbols>
36+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
37+
</PropertyGroup>
38+
<ItemGroup>
39+
<Reference Include="0Harmony, Version=2.5.4.0, Culture=neutral, processorArchitecture=MSIL">
40+
<HintPath>..\..\packages\IllusionLibs.BepInEx.Harmony.2.5.4\lib\net35\0Harmony.dll</HintPath>
41+
<Private>False</Private>
42+
</Reference>
43+
<Reference Include="Assembly-CSharp, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
44+
<SpecificVersion>False</SpecificVersion>
45+
<HintPath>..\..\..\IllusionLibs\packaging\SexyBeachPR\libraries\Assembly-CSharp.dll</HintPath>
46+
</Reference>
47+
<Reference Include="BepInEx, Version=5.4.15.0, Culture=neutral, processorArchitecture=MSIL">
48+
<HintPath>..\..\packages\IllusionLibs.BepInEx.5.4.15\lib\net35\BepInEx.dll</HintPath>
49+
<Private>False</Private>
50+
</Reference>
51+
<Reference Include="MonoMod.RuntimeDetour, Version=21.8.5.1, Culture=neutral, processorArchitecture=MSIL">
52+
<HintPath>..\..\packages\IllusionLibs.BepInEx.MonoMod.21.8.5.1\lib\net35\MonoMod.RuntimeDetour.dll</HintPath>
53+
<Private>False</Private>
54+
</Reference>
55+
<Reference Include="MonoMod.Utils, Version=21.8.5.1, Culture=neutral, processorArchitecture=MSIL">
56+
<HintPath>..\..\packages\IllusionLibs.BepInEx.MonoMod.21.8.5.1\lib\net35\MonoMod.Utils.dll</HintPath>
57+
<Private>False</Private>
58+
</Reference>
59+
<Reference Include="System.Core" />
60+
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
61+
<SpecificVersion>False</SpecificVersion>
62+
<HintPath>..\..\..\IllusionLibs\packaging\SexyBeachPR\libraries\UnityEngine.dll</HintPath>
63+
</Reference>
64+
</ItemGroup>
65+
<ItemGroup>
66+
<Compile Include="SBPR.ResourceUnloadOptimizations.cs" />
67+
</ItemGroup>
68+
<ItemGroup>
69+
<None Include="packages.config" />
70+
</ItemGroup>
71+
<ItemGroup>
72+
<Folder Include="Properties\" />
73+
</ItemGroup>
74+
<Import Project="..\Common\Common.projitems" Label="Shared" />
75+
<Import Project="..\Core_Fix_ResourceUnloadOptimizations\Core_Fix_ResourceUnloadOptimizations.projitems" Label="Shared" />
76+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
77+
<PropertyGroup>
78+
<PostBuildEvent>IF EXIST $(SolutionDir)PostBuild.bat CALL "$(SolutionDir)PostBuild.bat" $(TargetPath) SBPR</PostBuildEvent>
79+
</PropertyGroup>
80+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
81+
<PropertyGroup>
82+
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
83+
</PropertyGroup>
84+
<Error Condition="!Exists('..\..\packages\IllusionLibs.BepInEx.Harmony.2.5.4\build\IllusionLibs.BepInEx.Harmony.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\IllusionLibs.BepInEx.Harmony.2.5.4\build\IllusionLibs.BepInEx.Harmony.targets'))" />
85+
<Error Condition="!Exists('..\..\packages\IllusionLibs.BepInEx.MonoMod.21.8.5.1\build\IllusionLibs.BepInEx.MonoMod.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\IllusionLibs.BepInEx.MonoMod.21.8.5.1\build\IllusionLibs.BepInEx.MonoMod.targets'))" />
86+
</Target>
87+
<Import Project="..\..\packages\IllusionLibs.BepInEx.Harmony.2.5.4\build\IllusionLibs.BepInEx.Harmony.targets" Condition="Exists('..\..\packages\IllusionLibs.BepInEx.Harmony.2.5.4\build\IllusionLibs.BepInEx.Harmony.targets')" />
88+
<Import Project="..\..\packages\IllusionLibs.BepInEx.MonoMod.21.8.5.1\build\IllusionLibs.BepInEx.MonoMod.targets" Condition="Exists('..\..\packages\IllusionLibs.BepInEx.MonoMod.21.8.5.1\build\IllusionLibs.BepInEx.MonoMod.targets')" />
89+
</Project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<packages>
3+
<package id="IllusionLibs.BepInEx" version="5.4.15" targetFramework="net35" developmentDependency="true" />
4+
<package id="IllusionLibs.BepInEx.Harmony" version="2.5.4" targetFramework="net35" developmentDependency="true" />
5+
<package id="IllusionLibs.BepInEx.MonoMod" version="21.8.5.1" targetFramework="net35" developmentDependency="true" />
6+
<package id="Mono.Cecil" version="0.10.4" targetFramework="net35" />
7+
<package id="MonoMod.RuntimeDetour" version="19.8.2.3" targetFramework="net35" />
8+
<package id="MonoMod.Utils" version="19.8.2.3" targetFramework="net35" />
9+
</packages>

0 commit comments

Comments
 (0)