Decompiled source of LethalSponge v1.0.1
LethalSponge/LethalSponge.dll
Decompiled 3 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DunGen; using GameNetcodeStuff; using HarmonyLib; using LethalLevelLoader; using LethalLevelLoader.AssetBundles; using Microsoft.CodeAnalysis; using Scoops.compatibility; using Scoops.patches; using Scoops.rendering; using Scoops.service; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Experimental.Rendering; using UnityEngine.InputSystem; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("LethalLevelLoader")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: AssemblyCompany("LethalSponge")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.0.0.0")] [assembly: AssemblyInformationalVersion("0.0.0-alpha.0.28+cbee1cb789f0ec7a882f2c8ebe1bd4c8c1cb02b3")] [assembly: AssemblyProduct("LethalSponge")] [assembly: AssemblyTitle("LethalSponge")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Scoops { public class Config { public static ConfigEntry<bool> verboseLogging; public static ConfigEntry<bool> ignoreInactiveObjects; public static ConfigEntry<string> fullReportList; public static ConfigEntry<string> assetbundleBlacklist; public static ConfigEntry<string> assetbundleWhitelist; public static ConfigEntry<string> propertyBlacklist; public static ConfigEntry<bool> unloadUnused; public static ConfigEntry<bool> fixFoliageLOD; public static ConfigEntry<bool> fixInputActions; public static ConfigEntry<bool> fixCameraSettings; public static ConfigEntry<bool> patchCameraScript; public static ConfigEntry<int> mapCameraFramerate; public static ConfigEntry<int> securityCameraFramerate; public static ConfigEntry<bool> removePosterizationShader; public static ConfigEntry<bool> useCustomShader; public static ConfigEntry<bool> disableDOF; public static ConfigEntry<bool> disableMotionBlur; public static ConfigEntry<bool> disableBloom; public static ConfigEntry<bool> disableShadows; public static ConfigEntry<bool> disableReflections; public static ConfigEntry<bool> disableMotionVectors; public static ConfigEntry<bool> disableRefraction; public static ConfigEntry<bool> qualityOverrides; public static ConfigEntry<int> decalDrawDist; public static ConfigEntry<int> decalAtlasSize; public static ConfigEntry<string> reflectionAtlasSize; public static ConfigEntry<int> maxCubeReflectionProbes; public static ConfigEntry<int> maxPlanarReflectionProbes; public static ConfigEntry<int> shadowsMaxResolution; public static ConfigEntry<int> shadowsAtlasSize; public static ConfigEntry<float> fogBudget; public static ConfigEntry<bool> deferredOnly; public static ConfigEntry<bool> changeLightFadeDistance; public static ConfigEntry<float> lightVolumetricDistMult; public static ConfigEntry<float> lightVolumetricDistCap; public static ConfigEntry<bool> runDaily; public Config(ConfigFile cfg) { //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Expected O, but got Unknown //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Expected O, but got Unknown //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Expected O, but got Unknown //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Expected O, but got Unknown //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Expected O, but got Unknown //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Expected O, but got Unknown //IL_0450: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Expected O, but got Unknown //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Expected O, but got Unknown //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Expected O, but got Unknown verboseLogging = cfg.Bind<bool>("Investigation", "verboseLogging", false, "Whether Sponge should output detailed information about possible leak sources. (COSTLY FOR PERFORMANCE, ONLY ENABLE WHILE DEBUGGING)."); ignoreInactiveObjects = cfg.Bind<bool>("Investigation", "ignoreInactiveObjects", true, "Whether Sponge should exclude gameobjects/behaviors that are inactive from totals."); fullReportList = cfg.Bind<string>("Investigation", "fullReportList", "", "Bundles/Scenes in this semicolon-separated list will have all objects' Name and ID printed each check. Use 'unknown' for basegame/unknown sources."); assetbundleBlacklist = cfg.Bind<string>("Investigation", "assetbundleBlacklist", "", "Any objects originating from assetbundles/scenes in this list will never be reported. Use 'unknown' for basegame/unknown sources."); assetbundleWhitelist = cfg.Bind<string>("Investigation", "assetbundleWhitelist", "", "ONLY objects originating from assetbundles/scenes in this list will be reported. This takes precedence over the Blacklist. Use 'unknown' for basegame/unknown sources."); propertyBlacklist = cfg.Bind<string>("Investigation", "propertyBlacklist", "Renderer.material;Renderer.materials;LightProbes.GetInstantiatedLightProbesForScene;MeshFilter.mesh;Collider.material;TMP_Text.fontMaterial;TMP_Text.fontMaterials;TMP_Text.spriteAnimator;Graphic.materialForRendering;Volume.profile;Volume.profileRef;TMP_InputField.mesh;InputSystemUIInputModule.trackedDeviceSelect;BasePanel.dungeon;BasePanel.selectedExtendedDungeonFlow;BasePanel.selectedDungeonFlow;TMP_Text.fontSharedMaterials;RenderSettings.customReflection;NetworkManager.ConnectedClients;NetworkManager.ConnectedClientsList;NetworkManager.ConnectedClientsIds", "While crawling through objects/classes to find references, Sponge will ignore these properties. Useful if there are Getters that run unwanted code."); unloadUnused = cfg.Bind<bool>("Cleanup", "unloadUnused", true, "Should Sponge call UnloadUnusedAssets each day?"); fixFoliageLOD = cfg.Bind<bool>("Cleanup", "fixFoliageLOD", true, "Should Sponge replace the base Lethal Company FoliageDetailDistance script with one that doesn't leak materials? (LethalPerformance has a similar fix as well)"); fixInputActions = cfg.Bind<bool>("Cleanup", "fixInputActions", true, "Should Sponge fix the repeated instantiation of PlayerActions that would cause additional input lag every time a game is loaded?"); fixCameraSettings = cfg.Bind<bool>("Cameras", "fixCameraSettings", true, "Should Sponge change the settings for the ship cameras and radar cam to improve performance?"); patchCameraScript = cfg.Bind<bool>("Cameras", "patchCameraScript", true, "Should Sponge replace the base Lethal Company ManualCameraRenderer.MeetsCameraEnabledConditions function with one that more reliably disables ship cameras when they're not in view?"); securityCameraFramerate = cfg.Bind<int>("Cameras", "securityCameraFramerate", 15, "What framerate should the interior and exterior cams run at? (Requires fixCameraSettings = true)"); mapCameraFramerate = cfg.Bind<int>("Cameras", "mapCameraFramerate", 20, "What framerate should the radar map camera run at? (Requires fixCameraSettings = true)"); removePosterizationShader = cfg.Bind<bool>("Rendering", "removePosterizationShader", true, "Should Sponge remove the expensive posterization + outline custom pass to save processing power?"); useCustomShader = cfg.Bind<bool>("Rendering", "useCustomShader", true, "Should Sponge replace the removed shader with a faster one that looks similar? (Requires removePosterizationShader = true)"); disableDOF = cfg.Bind<bool>("Rendering", "disableDOF", false, "Should Sponge disable Depth of Field on the player camera?"); disableMotionBlur = cfg.Bind<bool>("Rendering", "disableMotionBlur", false, "Should Sponge disable Motion Blur on the player camera?"); disableBloom = cfg.Bind<bool>("Rendering", "disableBloom", false, "Should Sponge disable Bloom on the player camera?"); disableShadows = cfg.Bind<bool>("Rendering", "disableShadows", false, "Should Sponge disable Shadows on the player camera?"); disableReflections = cfg.Bind<bool>("Rendering", "disableReflections", false, "Should Sponge disable Reflections on the player camera?"); disableMotionVectors = cfg.Bind<bool>("Rendering", "disableReflections", false, "Should Sponge disable MotionVectors on the player camera?"); disableRefraction = cfg.Bind<bool>("Rendering", "disableReflections", false, "Should Sponge disable Refraction on the player camera?"); qualityOverrides = cfg.Bind<bool>("Graphics Quality", "qualityOverrides", true, "Should Sponge change the default quality settings? This must be on for any of the other Graphics Quality settings to take effect."); decalDrawDist = cfg.Bind<int>("Graphics Quality", "decalDrawDist", 100, new ConfigDescription("What should the maximum distance be for drawing decals like blood splatters? (LC default is 1000)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 100), Array.Empty<object>())); decalAtlasSize = cfg.Bind<int>("Graphics Quality", "decalAtlasSize", 2048, new ConfigDescription("What should the texture size be for the the Decal Atlas? (squared)", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[2] { 2048, 4096 }), Array.Empty<object>())); reflectionAtlasSize = cfg.Bind<string>("Graphics Quality", "reflectionAtlasSize", "Resolution1024x1024", new ConfigDescription("What should the texture size be for the the Decal Atlas? (LC default is 2048x1024)", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Resolution512x512", "Resolution1024x512", "Resolution1024x1024", "Resolution2048x1024" }), Array.Empty<object>())); maxCubeReflectionProbes = cfg.Bind<int>("Graphics Quality", "maxCubeReflectionProbes", 12, new ConfigDescription("How many Cube Reflection Probes should be able to be on screen at once? (LC default is 48)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(6, 48), Array.Empty<object>())); maxPlanarReflectionProbes = cfg.Bind<int>("Graphics Quality", "maxPlanarReflectionProbes", 8, new ConfigDescription("How many Cube Reflection Probes should be able to be on screen at once? (LC default is 16)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 16), Array.Empty<object>())); shadowsMaxResolution = cfg.Bind<int>("Graphics Quality", "shadowsMaxResolution", 256, new ConfigDescription("What should the maximum resolution be for Shadow Maps? (LC default is 1024)", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[5] { 64, 128, 256, 512, 1024 }), Array.Empty<object>())); shadowsAtlasSize = cfg.Bind<int>("Graphics Quality", "shadowsAtlasSize", 2048, new ConfigDescription("What should the resolution be for the Shadow Map Atlas? (LC default is 4096)", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[3] { 1024, 2048, 4096 }), Array.Empty<object>())); fogBudget = cfg.Bind<float>("Graphics Quality", "fogBudget", 0.15f, new ConfigDescription("What should the budget (0-1) be for the volumetric fog? (LC default is 0.166) (WARNING: Lowering this will make fog less dangerous)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.17f), Array.Empty<object>())); deferredOnly = cfg.Bind<bool>("Graphics Quality", "deferredOnly", true, "Should Sponge set the Lit Shader Mode to Deferred Only? (This might free up some memory, and LC only uses Deferred anyway.)"); changeLightFadeDistance = cfg.Bind<bool>("Graphics Quality", "changeLightFadeDistance", true, "Should Sponge change the Fade Distance for all lights so they're not visible from too far away?"); lightVolumetricDistMult = cfg.Bind<float>("Graphics Quality", "lightVolumetricDistMult", 10f, new ConfigDescription("What should the light's Range be multiplied by to find the Fade Distance?", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>())); lightVolumetricDistCap = cfg.Bind<float>("Graphics Quality", "lightVolumetricDistCap", 150f, new ConfigDescription("What should the maximum Fade Distance be for lights? (LC Defaults tend to use 10000 for Fade Distance)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(25f, 1000f), Array.Empty<object>())); runDaily = cfg.Bind<bool>("Debug", "runDaily", true, "If false, Sponge will no longer run automatically each day and will only run when you type '/sponge' in chat. This can be toggled mid-game with '/sponge toggle'."); } } public static class PluginInformation { public const string PLUGIN_GUID = "LethalSponge"; public const string PLUGIN_NAME = "LethalSponge"; public const string PLUGIN_VERSION = "1.0.1"; } [BepInPlugin("LethalSponge", "LethalSponge", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <RegisterAssetBundlesStale>d__14 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Plugin <>4__this; private GameObject[] <allGameObjects>5__1; private IEnumerable<AssetBundle> <allBundles>5__2; private IEnumerator<AssetBundle> <>s__3; private AssetBundle <bundle>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RegisterAssetBundlesStale>d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <allGameObjects>5__1 = null; <allBundles>5__2 = null; <>s__3 = null; <bundle>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 1; return true; case 1: <>1__state = -1; Log.LogMessage((object)"Sponge is acquiring assetbundle references, please wait."); <allGameObjects>5__1 = Resources.FindObjectsOfTypeAll<GameObject>(); <allBundles>5__2 = AssetBundle.GetAllLoadedAssetBundles(); <>s__3 = <allBundles>5__2.GetEnumerator(); try { while (<>s__3.MoveNext()) { <bundle>5__4 = <>s__3.Current; SpongeService.RegisterAssetBundle(<bundle>5__4); <bundle>5__4 = null; } } finally { if (<>s__3 != null) { <>s__3.Dispose(); } } <>s__3 = null; ((MonoBehaviour)<>4__this).StartCoroutine(SpongeService.CheckAllGameObjectDependencies(<allGameObjects>5__1)); Log.LogMessage((object)"Assetbundle references acquired."); <allGameObjects>5__1 = Array.Empty<GameObject>(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static AssetBundle SpongeAssets; private readonly Harmony _harmony = new Harmony("LethalSponge"); public static Plugin Instance { get; set; } public static Config SpongeConfig { get; internal set; } public static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger; public Plugin() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown Instance = this; } private void Awake() { Log.LogInfo((object)"Loading LethalSponge Version 1.0.1"); string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); string text = Path.Combine(directoryName, "spongeassets"); SpongeAssets = AssetBundle.LoadFromFile(text); SpongeConfig = new Config(((BaseUnityPlugin)this).Config); SpongeService.PluginLoad(); Log.LogInfo((object)"Applying base patches..."); ApplyPluginPatch(); Log.LogInfo((object)"Base patches applied"); if (Config.verboseLogging.Value) { Log.LogInfo((object)"Applying verbose patches..."); ApplyVerbosePluginPatch(); Log.LogInfo((object)"Verbose patches applied"); ((MonoBehaviour)this).StartCoroutine(RegisterAssetBundlesStale()); if (LLLCompat.Enabled) { Log.LogInfo((object)"Lethal Level Loader compat enabled..."); LLLCompat.AddBundleHook(); } } AlterQualitySettings(); } [IteratorStateMachine(typeof(<RegisterAssetBundlesStale>d__14))] public IEnumerator RegisterAssetBundlesStale() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RegisterAssetBundlesStale>d__14(0) { <>4__this = this }; } private void ApplyPluginPatch() { _harmony.PatchAll(typeof(StartOfRoundSpongePatch)); if (Config.fixFoliageLOD.Value) { _harmony.PatchAll(typeof(FoliageDetailDistanceSpongePatch)); } if (Config.patchCameraScript.Value) { _harmony.PatchAll(typeof(ManualCameraRendererSpongePatch)); } if (Config.disableBloom.Value || Config.disableDOF.Value || Config.disableMotionBlur.Value || Config.disableShadows.Value || Config.disableMotionVectors.Value || Config.disableRefraction.Value || Config.disableReflections.Value || Config.useCustomShader.Value) { _harmony.PatchAll(typeof(PlayerControllerBSpongePatch)); } if (Config.useCustomShader.Value) { _harmony.PatchAll(typeof(HDRenderPipeline_RecordRenderGraph_Patch)); } if (Config.fixInputActions.Value) { InputActionSpongePatches.Init(); _harmony.PatchAll(typeof(InputActionSpongePatches)); Log.LogInfo((object)"Input Actions Patched"); } } private void ApplyVerbosePluginPatch() { _harmony.PatchAll(typeof(RoundManagerSpongePatch)); _harmony.PatchAll(typeof(AssetBundleSpongePatch)); _harmony.PatchAll(typeof(AssetBundleAsyncSpongePatch)); _harmony.PatchAll(typeof(AssetBundleLoadSpongePatch)); _harmony.PatchAll(typeof(AssetBundleLoadAsyncSpongePatch)); _harmony.PatchAll(typeof(AssetBundleLoadMultipleSpongePatch)); _harmony.PatchAll(typeof(AssetBundleLoadMultipleAsyncSpongePatch)); } private void AlterQualitySettings() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (Config.qualityOverrides.Value) { RenderPipelineSettings currentPlatformRenderPipelineSettings = ((HDRenderPipelineAsset)GraphicsSettings.currentRenderPipeline).currentPlatformRenderPipelineSettings; if (Config.deferredOnly.Value) { currentPlatformRenderPipelineSettings.supportedLitShaderMode = (SupportedLitShaderMode)2; } currentPlatformRenderPipelineSettings.decalSettings.drawDistance = Config.decalDrawDist.Value; currentPlatformRenderPipelineSettings.decalSettings.atlasHeight = Config.decalAtlasSize.Value; currentPlatformRenderPipelineSettings.decalSettings.atlasWidth = Config.decalAtlasSize.Value; currentPlatformRenderPipelineSettings.lightLoopSettings.reflectionProbeTexCacheSize = Enum.Parse<ReflectionProbeTextureCacheResolution>(Config.reflectionAtlasSize.Value); currentPlatformRenderPipelineSettings.lightLoopSettings.maxCubeReflectionOnScreen = Config.maxCubeReflectionProbes.Value; currentPlatformRenderPipelineSettings.lightLoopSettings.maxPlanarReflectionOnScreen = Config.maxPlanarReflectionProbes.Value; currentPlatformRenderPipelineSettings.hdShadowInitParams.maxPunctualShadowMapResolution = Config.shadowsMaxResolution.Value; currentPlatformRenderPipelineSettings.hdShadowInitParams.maxDirectionalShadowMapResolution = Config.shadowsMaxResolution.Value; currentPlatformRenderPipelineSettings.hdShadowInitParams.maxAreaShadowMapResolution = Config.shadowsMaxResolution.Value; currentPlatformRenderPipelineSettings.hdShadowInitParams.punctualLightShadowAtlas.shadowAtlasResolution = Config.shadowsAtlasSize.Value; currentPlatformRenderPipelineSettings.hdShadowInitParams.cachedPunctualLightShadowAtlas = Config.shadowsAtlasSize.Value / 2; currentPlatformRenderPipelineSettings.hdShadowInitParams.areaLightShadowAtlas.shadowAtlasResolution = Config.shadowsAtlasSize.Value; currentPlatformRenderPipelineSettings.hdShadowInitParams.cachedAreaLightShadowAtlas = Config.shadowsAtlasSize.Value / 2; currentPlatformRenderPipelineSettings.lightingQualitySettings.Fog_Budget[QualitySettings.GetQualityLevel()] = Config.fogBudget.Value; ((HDRenderPipelineAsset)GraphicsSettings.currentRenderPipeline).m_RenderPipelineSettings = currentPlatformRenderPipelineSettings; ((RenderPipelineAsset)(HDRenderPipelineAsset)GraphicsSettings.currentRenderPipeline).OnValidate(); } } } public static class PluginInfo { public const string PLUGIN_GUID = "LethalSponge"; public const string PLUGIN_NAME = "LethalSponge"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace Scoops.service { public static class CameraService { public static Camera MapCamera; public static Camera ShipCamera; public static Camera SecurityCamera; public static GameObject MonitorWall; public static GameObject ShipInside; public static Terminal MainTerminal; public static GameObject oldVolume; public static GameObject newVolume; public static bool Init() { Plugin.Log.LogMessage((object)"Finding Ship cameras."); bool result = true; Camera val = (from x in Object.FindObjectsByType<Camera>((FindObjectsInactive)1, (FindObjectsSortMode)0) where ((Object)((Component)x).gameObject).name == "MapCamera" && ((Component)x).gameObject.tag == "MapCamera" select x).FirstOrDefault(); if ((Object)(object)val != (Object)null) { MapCamera = val; } else { Plugin.Log.LogError((object)"Sponge could not find MapCamera. Camera fixes may not function."); result = false; } Camera val2 = (from x in Object.FindObjectsByType<Camera>((FindObjectsInactive)1, (FindObjectsSortMode)0) where ((Object)((Component)x).gameObject).name == "ShipCamera" && ((Component)x).gameObject.tag == "Untagged" select x).FirstOrDefault(); if ((Object)(object)val2 != (Object)null) { ShipCamera = val2; } else { Plugin.Log.LogError((object)"Sponge could not find ShipCamera. Camera fixes may not function."); result = false; } Camera val3 = (from x in Object.FindObjectsByType<Camera>((FindObjectsInactive)1, (FindObjectsSortMode)0) where ((Object)((Component)x).gameObject).name == "SecurityCamera" && ((Component)x).gameObject.tag == "Untagged" select x).FirstOrDefault(); if ((Object)(object)val3 != (Object)null) { SecurityCamera = val3; } else { Plugin.Log.LogError((object)"Sponge could not find SecurityCamera. Camera fixes may not function."); result = false; } GameObject val4 = (from x in Object.FindObjectsByType<GameObject>((FindObjectsInactive)1, (FindObjectsSortMode)0) where ((Object)x).name == "MonitorWall" && x.gameObject.tag == "Untagged" select x).FirstOrDefault(); if ((Object)(object)val4 != (Object)null) { MonitorWall = val4; } else { Plugin.Log.LogError((object)"Sponge could not find MonitorWall. Camera fixes may not function."); result = false; } Terminal val5 = (from x in Object.FindObjectsByType<Terminal>((FindObjectsInactive)1, (FindObjectsSortMode)0) where ((Object)((Component)x).gameObject).name == "TerminalScript" && ((Component)x).gameObject.tag == "InteractTrigger" select x).FirstOrDefault(); if ((Object)(object)val5 != (Object)null) { MainTerminal = val5; } return result; } public static void DisablePosterization() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) oldVolume = GameObject.Find("CustomPass"); if (Config.useCustomShader.Value) { newVolume = Object.Instantiate<GameObject>((GameObject)Plugin.SpongeAssets.LoadAsset("SpongeCustomPass"), oldVolume.transform.parent); Plugin.SpongeAssets.LoadAsset("SpongePosterize"); Plugin.SpongeAssets.LoadAsset("FullScreen_SpongePosterize"); newVolume.GetComponent<CustomPassVolume>().injectionPoint = (CustomPassInjectionPoint)7; newVolume.GetComponent<CustomPassVolume>().customPasses.Clear(); newVolume.GetComponent<CustomPassVolume>().customPasses.Add((CustomPass)(object)new SpongeCustomPass()); } foreach (CustomPass customPass in oldVolume.GetComponent<CustomPassVolume>().customPasses) { if (customPass.name == "FS") { oldVolume.GetComponent<CustomPassVolume>().customPasses.Remove(customPass); break; } } } public static void ApplyCameraFixes() { SetOverrides(ShipCamera); SetOverrides(SecurityCamera); SetOverrides(MapCamera, mapCamera: true); ShipCamera.farClipPlane = 13f; SecurityCamera.farClipPlane = 20f; ((Component)ShipCamera).GetComponent<ManualCameraRenderer>().renderAtLowerFramerate = true; ((Component)ShipCamera).GetComponent<ManualCameraRenderer>().fps = Config.securityCameraFramerate.Value; ((Component)SecurityCamera).GetComponent<ManualCameraRenderer>().renderAtLowerFramerate = true; ((Component)SecurityCamera).GetComponent<ManualCameraRenderer>().fps = Config.securityCameraFramerate.Value; ((Component)MonitorWall.transform.Find("Cube.001/CameraMonitorScript")).GetComponent<ManualCameraRenderer>().renderAtLowerFramerate = true; ((Component)MonitorWall.transform.Find("Cube.001/CameraMonitorScript")).GetComponent<ManualCameraRenderer>().fps = Config.mapCameraFramerate.Value; Plugin.Log.LogMessage((object)"Ship cameras patched."); } public static void ApplyPlayerCameraPatch(PlayerControllerB player) { if (Config.disableBloom.Value || Config.disableDOF.Value || Config.disableMotionBlur.Value || Config.disableShadows.Value || Config.disableMotionVectors.Value || Config.disableRefraction.Value || Config.disableReflections.Value) { SetPlayerOverrides(player.gameplayCamera); } if (Config.useCustomShader.Value) { HDAdditionalCameraData component = ((Component)player.gameplayCamera).GetComponent<HDAdditionalCameraData>(); UpdateCamera(player.gameplayCamera); } Plugin.Log.LogMessage((object)"Player camera patched."); } public static void UpdateCamera(Camera camera) { newVolume.GetComponent<CustomPassVolume>().targetCamera = camera; if ((Object)(object)camera.targetTexture != (Object)null) { if (SpongeCustomPass.posterizationRT != null) { RTHandles.Release(SpongeCustomPass.posterizationRT); } SpongeCustomPass.posterizationRT = RTHandles.Alloc(((Texture)camera.targetTexture).width, ((Texture)camera.targetTexture).height, 1, (DepthBits)0, (GraphicsFormat)4, (FilterMode)0, (TextureWrapMode)1, (TextureDimension)2, true, false, true, false, 1, 0f, (MSAASamples)1, false, false, (RenderTextureMemoryless)0, (VRTextureUsage)0, ""); } } private static void SetOverrides(Camera camera, bool mapCamera = false) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) HDAdditionalCameraData component = ((Component)camera).GetComponent<HDAdditionalCameraData>(); component.customRenderingSettings = true; ((BitArray128)(ref component.renderingPathCustomFrameSettingsOverrideMask.mask))[4u] = true; component.renderingPathCustomFrameSettings.msaaMode = (MSAAMode)1; if (!mapCamera) { ((BitArray128)(ref component.renderingPathCustomFrameSettingsOverrideMask.mask))[62u] = true; ((BitArray128)(ref component.renderingPathCustomFrameSettingsOverrideMask.mask))[63u] = true; component.renderingPathCustomFrameSettings.maximumLODLevelMode = (MaximumLODLevelMode)2; component.renderingPathCustomFrameSettings.maximumLODLevel = 2; } ((BitArray128)(ref component.renderingPathCustomFrameSettingsOverrideMask.mask))[66u] = true; component.renderingPathCustomFrameSettings.materialQuality = (MaterialQuality)1; if (!mapCamera) { component.DisableHDField((FrameSettingsField)3); } component.DisableHDField((FrameSettingsField)12); component.DisableHDField((FrameSettingsField)8); component.DisableHDField((FrameSettingsField)9); component.DisableHDField((FrameSettingsField)92); component.DisableHDField((FrameSettingsField)6); component.DisableHDField((FrameSettingsField)10); component.DisableHDField((FrameSettingsField)13); component.DisableHDField((FrameSettingsField)14); component.DisableHDField((FrameSettingsField)39); component.DisableHDField((FrameSettingsField)80); component.DisableHDField((FrameSettingsField)81); component.DisableHDField((FrameSettingsField)82); component.DisableHDField((FrameSettingsField)83); component.DisableHDField((FrameSettingsField)84); component.DisableHDField((FrameSettingsField)85); component.DisableHDField((FrameSettingsField)86); component.DisableHDField((FrameSettingsField)87); component.DisableHDField((FrameSettingsField)89); component.DisableHDField((FrameSettingsField)90); component.DisableHDField((FrameSettingsField)91); component.DisableHDField((FrameSettingsField)93); component.DisableHDField((FrameSettingsField)97); component.DisableHDField((FrameSettingsField)17); component.DisableHDField((FrameSettingsField)68); component.DisableHDField((FrameSettingsField)99); component.DisableHDField((FrameSettingsField)20); component.DisableHDField((FrameSettingsField)21); component.DisableHDField((FrameSettingsField)127); component.DisableHDField((FrameSettingsField)34); component.DisableHDField((FrameSettingsField)23); component.DisableHDField((FrameSettingsField)95); component.DisableHDField((FrameSettingsField)24); component.DisableHDField((FrameSettingsField)26); component.DisableHDField((FrameSettingsField)27); component.DisableHDField((FrameSettingsField)33); component.DisableHDField((FrameSettingsField)35); component.DisableHDField((FrameSettingsField)37); component.DisableHDField((FrameSettingsField)46); component.DisableHDField((FrameSettingsField)79); if (mapCamera) { component.DisableHDField((FrameSettingsField)38); } } private static void SetPlayerOverrides(Camera camera, bool potato = false) { HDAdditionalCameraData component = ((Component)camera).GetComponent<HDAdditionalCameraData>(); component.customRenderingSettings = true; ((BitArray128)(ref component.renderingPathCustomFrameSettingsOverrideMask.mask))[15u] = true; if (Config.disableBloom.Value) { component.DisableHDField((FrameSettingsField)84); } if (Config.disableDOF.Value) { component.DisableHDField((FrameSettingsField)81); } if (Config.disableMotionBlur.Value) { component.DisableHDField((FrameSettingsField)82); } if (Config.disableShadows.Value) { component.DisableHDField((FrameSettingsField)20); component.DisableHDField((FrameSettingsField)21); component.DisableHDField((FrameSettingsField)34); } if (Config.disableReflections.Value) { component.DisableHDField((FrameSettingsField)33); component.DisableHDField((FrameSettingsField)35); component.DisableHDField((FrameSettingsField)37); component.DisableHDField((FrameSettingsField)23); component.DisableHDField((FrameSettingsField)94); } if (Config.disableMotionVectors.Value) { component.DisableHDField((FrameSettingsField)10); component.DisableHDField((FrameSettingsField)11); component.DisableHDField((FrameSettingsField)16); } if (Config.disableRefraction.Value) { component.DisableHDField((FrameSettingsField)13); } } private static void DisableHDField(this HDAdditionalCameraData data, FrameSettingsField field) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected I4, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) ((BitArray128)(ref data.renderingPathCustomFrameSettingsOverrideMask.mask))[(uint)(int)field] = true; ((FrameSettings)(ref data.renderingPathCustomFrameSettings)).SetEnabled(field, false); } } public static class LightService { public static void UpdateAllLights() { HDAdditionalLightData[] array = Object.FindObjectsByType<HDAdditionalLightData>((FindObjectsInactive)1, (FindObjectsSortMode)0); float value = Config.lightVolumetricDistMult.Value; float value2 = Config.lightVolumetricDistCap.Value; HDAdditionalLightData[] array2 = array; foreach (HDAdditionalLightData val in array2) { val.fadeDistance = Math.Clamp(value * val.range, 0f, value2); } } } public enum SpongeMode { Evaluate, Clean, Full } internal class BundleLeakTracker { public Dictionary<string, int> leakCount; public Dictionary<string, int> objectCount; public BundleLeakTracker() { leakCount = new Dictionary<string, int>(); objectCount = new Dictionary<string, int>(); } } internal static class SpongeService { [CompilerGenerated] private sealed class <CheckAllGameObjectDependencies>d__35 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject[] allGameObjects; private List<string> <checkedObjects>5__1; private GameObject[] <>s__2; private int <>s__3; private GameObject <obj>5__4; private string <bundleName>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CheckAllGameObjectDependencies>d__35(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <checkedObjects>5__1 = null; <>s__2 = null; <obj>5__4 = null; <bundleName>5__5 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <checkedObjects>5__1 = new List<string>(); <>s__2 = allGameObjects; for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++) { <obj>5__4 = <>s__2[<>s__3]; if (!<checkedObjects>5__1.Contains(((Object)<obj>5__4).name) && (Object)(object)<obj>5__4.transform.parent == (Object)null) { if (bundleTracking.TryGetValue(((Object)<obj>5__4).name.ToLower(), out <bundleName>5__5)) { <checkedObjects>5__1.Add(((Object)<obj>5__4).name); FindGameObjectDependenciesRecursively(<bundleName>5__5, <obj>5__4); } <bundleName>5__5 = null; } <obj>5__4 = null; } <>s__2 = null; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static bool enabled = true; private static readonly Dictionary<Type, List<FieldInfo>> assignableFieldsByObjectType = new Dictionary<Type, List<FieldInfo>> { { typeof(Object), null } }; private static readonly Dictionary<Type, List<PropertyInfo>> assignablePropertiesByObjectType = new Dictionary<Type, List<PropertyInfo>> { { typeof(Object), null } }; private static Object[] allObjects; private static List<string> ignoredProperties = new List<string>(); private static List<string> ignoredAssetbundles = new List<string>(); private static List<string> focusedAssetbundles = new List<string>(); private static List<string> fullReportBundles = new List<string>(); private static Dictionary<string, BundleLeakTracker> leakTracking = new Dictionary<string, BundleLeakTracker>(); private static Dictionary<string, BundleLeakTracker> previousLeakTracking = new Dictionary<string, BundleLeakTracker>(); private static Dictionary<int, ushort> referenceTracking = new Dictionary<int, ushort>(); private static Dictionary<string, string> bundleTracking = new Dictionary<string, string>(); private static Dictionary<string, string> streamedSceneTracking = new Dictionary<string, string>(); private static Stopwatch stopwatch = new Stopwatch(); private static int prevCount = 0; private static int initialCount = 0; private static int newCount = 0; private static readonly List<string> meshReadProperties = new List<string> { "vertices", "normals", "tangents", "uv", "uv2", "uv3", "uv4", "uv5", "uv6", "uv7", "uv8", "colors", "colors32", "triangles" }; public static void PluginLoad() { ParseConfig(); SceneManager.sceneLoaded += SceneLoaded; } public static void Initialize() { Plugin.Log.LogMessage((object)"---"); Plugin.Log.LogMessage((object)"Initializing Sponge"); allObjects = Resources.FindObjectsOfTypeAll<Object>(); Plugin.Log.LogMessage((object)("Initial count of " + allObjects.Length + " objects loaded.")); prevCount = allObjects.Length; initialCount = allObjects.Length; allObjects = Array.Empty<Object>(); Plugin.Log.LogMessage((object)"Type '/sponge help' in chat for commands."); Plugin.Log.LogMessage((object)"Sponge Initialised."); Plugin.Log.LogMessage((object)"---"); } public static void ParseConfig() { if (Config.propertyBlacklist.Value != "") { ignoredProperties.AddRange(Config.propertyBlacklist.Value.ToLower().Split(';')); } if (Config.assetbundleBlacklist.Value != "") { ignoredAssetbundles.AddRange(Config.assetbundleBlacklist.Value.ToLower().Split(';')); } if (Config.assetbundleWhitelist.Value != "") { focusedAssetbundles.AddRange(Config.assetbundleWhitelist.Value.ToLower().Split(';')); } if (Config.fullReportList.Value != "") { fullReportBundles.AddRange(Config.fullReportList.Value.ToLower().Split(';')); } enabled = Config.runDaily.Value; } public static bool AssetBundleValid(string bundleName) { if (focusedAssetbundles.Count > 0) { return focusedAssetbundles.Contains(bundleName.ToLower()); } return !ignoredAssetbundles.Contains(bundleName.ToLower()); } public static void ApplySponge(SpongeMode mode = SpongeMode.Full) { Plugin.Log.LogMessage((object)"---"); Plugin.Log.LogMessage((object)"Applying Sponge"); stopwatch.Restart(); if (Config.verboseLogging.Value && (mode == SpongeMode.Evaluate || mode == SpongeMode.Full)) { PerformEvaluation(); } allObjects = Resources.FindObjectsOfTypeAll<Object>(); newCount = allObjects.Length; Plugin.Log.LogMessage((object)("There are " + newCount + " loaded objects total.")); if (Config.verboseLogging.Value && (mode == SpongeMode.Evaluate || mode == SpongeMode.Full) && newCount > allObjects.Length) { Plugin.Log.LogWarning((object)"More objects after evaluating than before. Property calls possibly instantiated unexpected objects."); } allObjects = Array.Empty<Object>(); if (mode == SpongeMode.Clean || mode == SpongeMode.Full) { PerformCleanup(); } } private static void FinishSponge() { if (Config.unloadUnused.Value) { Plugin.Log.LogMessage((object)"Resources.UnloadUnusedAssets() completed."); allObjects = Resources.FindObjectsOfTypeAll<Object>(); int num = newCount; newCount = allObjects.Length; Plugin.Log.LogMessage((object)("After cleaning there are " + newCount + " loaded objects total.")); Plugin.Log.LogMessage((object)("Resources.UnloadUnusedAssets() cleaned up " + (num - newCount) + " objects.")); allObjects = Array.Empty<Object>(); } stopwatch.Stop(); TimeSpan elapsed = stopwatch.Elapsed; int num2 = newCount - initialCount; float num3 = (float)num2 / (float)initialCount * 100f; int num4 = newCount - prevCount; float num5 = (float)num4 / (float)prevCount * 100f; string text = "more"; if (num4 < 0) { text = "less"; } Plugin.Log.LogMessage((object)("Sponge took " + elapsed.TotalSeconds + " seconds to execute.")); Plugin.Log.LogMessage((object)("There were " + num2 + " more objects than on initialization, a " + num3 + "% change.")); Plugin.Log.LogMessage((object)("There were " + num4 + " " + text + " objects than last check, a " + num5 + "% change.")); Plugin.Log.LogMessage((object)"---"); prevCount = newCount; } private static void PerformEvaluation() { allObjects = Resources.FindObjectsOfTypeAll<Object>(); referenceTracking.Clear(); previousLeakTracking = leakTracking; leakTracking = new Dictionary<string, BundleLeakTracker>(); Plugin.Log.LogMessage((object)"Evaluating loaded objects, please wait."); for (int i = 0; i < allObjects.Length; i++) { IncrementReferenceCounts(GetUnityObjectReferences(i)); } int num = ExamineType<Mesh>(); int num2 = ExamineType<Material>(); int num3 = ExamineType<Texture2D>(); int num4 = ExamineType<AudioClip>(); int num5 = ExamineType<NavMeshData>(); int num6 = CountType<GameObject>(); int num7 = CountType<Camera>(); foreach (string key in leakTracking.Keys) { if (key != "unknown") { Plugin.Log.LogMessage((object)("For AssetBundle/Scene " + key + ": ")); } else { Plugin.Log.LogMessage((object)"For Base Game/unknown AssetBundle sources: "); } BundleLeakTracker bundleLeakTracker = leakTracking[key]; BundleLeakTracker value; bool flag = previousLeakTracking.TryGetValue(key, out value); if (!flag) { Plugin.Log.LogMessage((object)" - AssetBundle/Scene was not present on previous checks."); } foreach (string key2 in bundleLeakTracker.leakCount.Keys) { int num8 = bundleLeakTracker.leakCount[key2]; Plugin.Log.LogMessage((object)(" - " + num8 + " " + key2 + " with no known native unity references.")); if (flag && value.leakCount.ContainsKey(key2)) { int num9 = value.leakCount[key2]; if (num8 > num9) { Plugin.Log.LogMessage((object)(" - " + (num8 - num9) + " more than last check.")); } } } foreach (string key3 in bundleLeakTracker.objectCount.Keys) { int num10 = bundleLeakTracker.objectCount[key3]; Plugin.Log.LogMessage((object)(" - " + num10 + " " + (Config.ignoreInactiveObjects.Value ? "Active " : "") + key3 + ".")); if (flag && value.objectCount.ContainsKey(key3)) { int num11 = value.objectCount[key3]; if (num10 > num11) { Plugin.Log.LogMessage((object)(" - " + (num10 - num11) + " more than last check.")); } } } } Plugin.Log.LogMessage((object)"The above counts may be inaccurate, use them as approximations. Objects can be attributed to the wrong bundle/scene in the case of overlapping names."); Plugin.Log.LogMessage((object)"Remember that Meshes, Textures, and Materials should be cleaned up manually, but if they have no native unity references they will be cleaned up by UnloadUnusedAssets."); Plugin.Log.LogMessage((object)"Unwanted GameObjects will never be cleaned up automatically. Large amounts of GameObjects can be fine, but if these increase day over day there may be an issue."); } private static void PerformCleanup() { if (Config.unloadUnused.Value) { Plugin.Log.LogMessage((object)"Calling Resources.UnloadUnusedAssets()."); Resources.UnloadUnusedAssets().completed += delegate { FinishSponge(); }; } else { FinishSponge(); } } private static int ExamineType<T>() where T : Object { int num = 0; T[] array = Resources.FindObjectsOfTypeAll<T>(); for (int i = 0; i < array.Length; i++) { int instanceID = ((Object)array[i]).GetInstanceID(); if ((!referenceTracking.TryGetValue(instanceID, out var value) || value < 1) && HandleLeakedObject((Object)(object)array[i])) { num++; } } array = Array.Empty<T>(); if (num > 0) { Plugin.Log.LogMessage((object)("Found " + num + " " + typeof(T).Name + " with no known references.")); } return num; } private static int CountType<T>() where T : Object { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) int num = 0; T[] array = Resources.FindObjectsOfTypeAll<T>(); for (int i = 0; i < array.Length; i++) { string text = TryGetObjectBundleName(((Object)array[i]).name); if (!AssetBundleValid(text)) { continue; } if (typeof(GameObject).IsAssignableFrom(typeof(T))) { object obj = array[i]; GameObject val = (GameObject)((obj is GameObject) ? obj : null); Scene scene = val.scene; if (((Scene)(ref scene)).name == null) { continue; } scene = val.scene; if (((Scene)(ref scene)).name == ((Object)val).name || (Config.ignoreInactiveObjects.Value && !val.activeInHierarchy)) { continue; } } if (typeof(Component).IsAssignableFrom(typeof(T))) { object obj2 = array[i]; Behaviour val2 = (Behaviour)((obj2 is Behaviour) ? obj2 : null); if (Config.ignoreInactiveObjects.Value && (!val2.enabled || !((Component)val2).gameObject.activeInHierarchy)) { continue; } } string name = typeof(T).Name; if (fullReportBundles.Contains(text.ToLower())) { Plugin.Log.LogMessage((object)("Counted " + (Config.ignoreInactiveObjects.Value ? "Active " : "") + name + " with name '" + ((Object)array[i]).name + "' and ID '" + ((Object)array[i]).GetInstanceID() + "' from bundle/scene " + text + ".")); } num++; if (leakTracking.ContainsKey(text)) { leakTracking[text].objectCount.TryGetValue(name, out var value); leakTracking[text].objectCount[name] = value + 1; } else { leakTracking.Add(text, new BundleLeakTracker()); leakTracking[text].objectCount.Add(name, 1); } } array = Array.Empty<T>(); if (num > 0) { Plugin.Log.LogMessage((object)("Found " + num + " " + (Config.ignoreInactiveObjects.Value ? "Active " : "") + typeof(T).Name + ".")); } return num; } public static void ModelCheck() { //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogMessage((object)"---"); Plugin.Log.LogMessage((object)"Running Sponge Model Check."); int num = 0; int num2 = 0; Dictionary<string, Vector2Int> dictionary = new Dictionary<string, Vector2Int>(); HashSet<Mesh> hashSet = new HashSet<Mesh>(); List<MeshFilter> list = new List<MeshFilter>(10); MeshFilter[] array = Object.FindObjectsByType<MeshFilter>((FindObjectsInactive)0, (FindObjectsSortMode)0); MeshFilter[] array2 = array; Vector2Int val2 = default(Vector2Int); foreach (MeshFilter val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || hashSet.Contains(val.sharedMesh)) { continue; } string text = TryGetObjectBundleName(((Object)val.sharedMesh).name); if (!AssetBundleValid(text)) { continue; } Renderer component = ((Component)val).gameObject.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null || !component.isVisible) { continue; } int vertexCount = val.sharedMesh.vertexCount; ((Vector2Int)(ref val2))..ctor(vertexCount, 1); num2 += vertexCount; num++; dictionary.TryGetValue(text, out var value); dictionary[text] = value + val2; hashSet.Add(val.sharedMesh); if ((list.Count < 10 || list[0].sharedMesh.vertexCount < vertexCount) && !list.Contains(val)) { if (list.Count == 10) { list[0] = val; } else { list.Add(val); } list.Sort((MeshFilter a, MeshFilter b) => a.sharedMesh.vertexCount.CompareTo(b.sharedMesh.vertexCount)); } if (vertexCount <= 1000) { continue; } Bounds bounds = component.bounds; float x = ((Bounds)(ref bounds)).size.x; bounds = component.bounds; float num3 = x * ((Bounds)(ref bounds)).size.y; bounds = component.bounds; float num4 = num3 * ((Bounds)(ref bounds)).size.z; float num5 = (float)vertexCount / num4; if (num5 > 5000f) { Plugin.Log.LogWarning((object)("Mesh " + ((Object)val.sharedMesh).name + " for GameObject " + ((Object)((Component)val).gameObject).name + " has vertex density of " + num5)); Transform val3 = ((Component)val).gameObject.transform; while ((Object)(object)val3.parent != (Object)null) { val3 = val3.parent; } Plugin.Log.LogWarning((object)(" - " + vertexCount + " vertices over " + num4 + " cubed meters.")); Plugin.Log.LogWarning((object)(" - On root GameObject " + ((Object)((Component)val3).gameObject).name + ".")); if (text != "unknown") { Plugin.Log.LogWarning((object)(" - From the bundle '" + text + "'")); } } } Plugin.Log.LogMessage((object)("Found " + num + " Visible Meshes.")); Plugin.Log.LogMessage((object)("With " + num2 + " Vertices total.")); foreach (string key in dictionary.Keys) { if (!(key == "unknown")) { ManualLogSource log = Plugin.Log; string[] obj = new string[5] { " - Bundle '", key, "' contributed ", null, null }; Vector2Int val4 = dictionary[key]; obj[3] = ((Vector2Int)(ref val4)).y.ToString(); obj[4] = " Visible Meshes"; log.LogMessage((object)string.Concat(obj)); ManualLogSource log2 = Plugin.Log; val4 = dictionary[key]; log2.LogMessage((object)(" and " + ((Vector2Int)(ref val4)).x + " Vertices total.")); } } Plugin.Log.LogMessage((object)("The " + list.Count + " largest meshes were:")); foreach (MeshFilter item in list) { string text2 = TryGetObjectBundleName(((Object)item.sharedMesh).name); Plugin.Log.LogMessage((object)(" - Mesh '" + ((Object)item.sharedMesh).name + "' with " + item.sharedMesh.vertexCount + " Vertices")); Plugin.Log.LogMessage((object)(" on the GameObject with the name '" + ((Object)((Component)item).gameObject).name + "'")); if (text2 != "unknown") { Plugin.Log.LogMessage((object)(" from the bundle '" + text2 + "'")); } } Plugin.Log.LogMessage((object)"The above counts may be inaccurate. Meshes can be attributed to the wrong bundle/scene in the case of overlapping names."); Plugin.Log.LogMessage((object)"---"); } public static void TextureCheck() { //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0546: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Invalid comparison between Unknown and I4 //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogMessage((object)"---"); Plugin.Log.LogMessage((object)"Running Sponge Texture Check."); int num = 0; int num2 = 0; Dictionary<string, Vector2Int> dictionary = new Dictionary<string, Vector2Int>(); HashSet<Texture> hashSet = new HashSet<Texture>(); List<Texture> list = new List<Texture>(10); Renderer[] array = Object.FindObjectsByType<Renderer>((FindObjectsInactive)0, (FindObjectsSortMode)0); Renderer[] array2 = array; Vector2Int val3 = default(Vector2Int); foreach (Renderer val in array2) { if ((Object)(object)val == (Object)null || !val.isVisible) { continue; } Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if ((Object)(object)val2 == (Object)null || (Object)(object)val2.shader == (Object)null || val2.shader.GetPropertyCount() == 0) { continue; } List<Texture> list2 = new List<Texture>(); for (int k = 0; k < val2.shader.GetPropertyCount(); k++) { if ((int)val2.shader.GetPropertyType(k) == 4) { Texture texture = val2.GetTexture(val2.shader.GetPropertyName(k)); if ((Object)(object)texture != (Object)null) { list2.Add(texture); } } } foreach (Texture item in list2) { if (hashSet.Contains(item)) { continue; } string text = TryGetObjectBundleName(((Object)item).name); if (!AssetBundleValid(text)) { continue; } int num3 = item.height * item.width; ((Vector2Int)(ref val3))..ctor(num2, 1); num2 += num3; num++; dictionary.TryGetValue(text, out var value); dictionary[text] = value + val3; hashSet.Add(item); if ((list.Count < 10 || list[0].height * list[0].width < num3) && !list.Contains(item)) { if (list.Count == 10) { list[0] = item; } else { list.Add(item); } list.Sort((Texture a, Texture b) => (a.height * a.width).CompareTo(b.height * b.width)); } if (num3 <= 1048576) { continue; } Bounds bounds = val.bounds; float x = ((Bounds)(ref bounds)).size.x; bounds = val.bounds; float y = ((Bounds)(ref bounds)).size.y; bounds = val.bounds; float num4 = Mathf.Max(x, Mathf.Max(y, ((Bounds)(ref bounds)).size.z)); float num5 = num4 * num4 * num4; float num6 = (float)num3 / num5; if (num6 > 500000f) { Plugin.Log.LogWarning((object)("Texture " + ((Object)item).name + " for GameObject " + ((Object)((Component)val).gameObject).name + " has pixel density of " + num6)); Transform val4 = ((Component)val).gameObject.transform; while ((Object)(object)val4.parent != (Object)null) { val4 = val4.parent; } Plugin.Log.LogWarning((object)(" - Dimensions " + item.width + "x" + item.height + " for " + num5 + " cubed meters.")); Plugin.Log.LogWarning((object)(" - On root GameObject " + ((Object)((Component)val4).gameObject).name + ".")); if (text != "unknown") { Plugin.Log.LogWarning((object)(" - From the bundle '" + text + "'")); } } } } } Plugin.Log.LogMessage((object)("Found " + num + " Visible Textures.")); Plugin.Log.LogMessage((object)("With " + num2 + " Pixels total.")); foreach (string key in dictionary.Keys) { if (!(key == "unknown")) { ManualLogSource log = Plugin.Log; string[] obj = new string[5] { " - Bundle '", key, "' contributed ", null, null }; Vector2Int val5 = dictionary[key]; obj[3] = ((Vector2Int)(ref val5)).y.ToString(); obj[4] = " Visible Textures"; log.LogMessage((object)string.Concat(obj)); ManualLogSource log2 = Plugin.Log; val5 = dictionary[key]; log2.LogMessage((object)(" and " + ((Vector2Int)(ref val5)).x + " Pixels total.")); } } Plugin.Log.LogMessage((object)("The " + list.Count + " largest textures were:")); foreach (Texture item2 in list) { string text2 = TryGetObjectBundleName(((Object)item2).name); Plugin.Log.LogMessage((object)(" - Texture '" + ((Object)item2).name + "' with dimensions " + item2.width + "x" + item2.height)); if (text2 != "unknown") { Plugin.Log.LogMessage((object)(" from the bundle '" + text2 + "'")); } } Plugin.Log.LogMessage((object)"The above counts may be inaccurate. Textures can be attributed to the wrong bundle/scene in the case of overlapping names."); Plugin.Log.LogMessage((object)"---"); } public static void SceneLoaded(Scene scene, LoadSceneMode mode) { if (Config.verboseLogging.Value) { streamedSceneTracking.TryGetValue(((Scene)(ref scene)).name, out var value); GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject obj in rootGameObjects) { FindGameObjectDependenciesRecursively(value ?? ((Scene)(ref scene)).name, obj); } } } public static void DungeonLoaded(DungeonGenerator generator) { bundleTracking.TryGetValue(((Object)generator.DungeonFlow).name, out var value); FindGameObjectDependenciesRecursively(value ?? ((Object)generator.DungeonFlow).name, generator.Root); } public static void ObjectLoaded(AssetBundle bundle, Object obj) { string bundleName = FormatBundleName(((Object)bundle).name); GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null); Component val2 = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null) { FindGameObjectDependenciesRecursively(bundleName, val); } else if ((Object)(object)val2 != (Object)null) { BuildBundleDependencies(bundleName, GetUnityObjectReferences((Object)(object)val2)); } else { BuildBundleDependencies(bundleName, obj); } } public static void FindGameObjectDependenciesRecursively(string bundleName, GameObject obj) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown bundleTracking[((Object)obj).name.ToLower()] = bundleName; Component[] components = obj.GetComponents(typeof(Component)); foreach (Component val in components) { if ((Object)(object)val != (Object)null) { BuildBundleDependencies(bundleName, GetUnityObjectReferences((Object)(object)val)); } } foreach (Transform item in obj.transform) { Transform val2 = item; FindGameObjectDependenciesRecursively(bundleName, ((Component)val2).gameObject); } } public static void RegisterAssetBundle(AssetBundle bundle) { string value = FormatBundleName(((Object)bundle).name); if (bundle.isStreamedSceneAssetBundle) { string[] allScenePaths = bundle.GetAllScenePaths(); foreach (string path in allScenePaths) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); streamedSceneTracking.TryAdd(fileNameWithoutExtension, value); } } else { string[] allAssetNames = bundle.GetAllAssetNames(); foreach (string path2 in allAssetNames) { string key = Path.GetFileNameWithoutExtension(path2).ToLower(); bundleTracking.TryAdd(key, value); } } } [IteratorStateMachine(typeof(<CheckAllGameObjectDependencies>d__35))] public static IEnumerator CheckAllGameObjectDependencies(GameObject[] allGameObjects) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CheckAllGameObjectDependencies>d__35(0) { allGameObjects = allGameObjects }; } private static string FormatBundleName(string bundleName) { return ((bundleName == null || bundleName == "") ? "unknown" : bundleName).ToLower(); } private static bool HandleLeakedObject(Object leakedObj) { string text = TryGetObjectBundleName(leakedObj.name); if (!AssetBundleValid(text)) { return false; } string name = ((object)leakedObj).GetType().Name; if (fullReportBundles.Contains(text)) { Plugin.Log.LogMessage((object)("Found suspected leaked " + name + " with name '" + leakedObj.name + "' and ID '" + leakedObj.GetInstanceID() + "' from bundle/scene " + text + ".")); } if (leakTracking.ContainsKey(text)) { leakTracking[text].leakCount.TryGetValue(name, out var value); leakTracking[text].leakCount[name] = value + 1; } else { leakTracking.Add(text, new BundleLeakTracker()); leakTracking[text].leakCount.Add(name, 1); } return true; } private static string TryGetObjectBundleName(string name) { string text = name.ToLower(); bundleTracking.TryGetValue(text, out var value); if (value == null) { bundleTracking.TryGetValue(text.Replace(" (instance)", ""), out value); } if (value == null) { bundleTracking.TryGetValue(text.Replace("(clone)", ""), out value); } if (value == null) { return "unknown"; } return value; } public static List<Object> GetUnityObjectReferences(int index) { Object val = allObjects[index]; if (val == (Object)null || val == null) { return new List<Object>(); } return GetUnityObjectReferences(val); } public static List<Object> GetUnityObjectReferences(Object target) { //IL_058d: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Expected O, but got Unknown //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Expected O, but got Unknown //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Expected O, but got Unknown List<Object> list = new List<Object>(); Type type = ((object)target).GetType(); try { if (((object)target).GetType() == typeof(Camera)) { return list; } if (!assignableFieldsByObjectType.TryGetValue(type, out var value)) { Type type2 = type; List<FieldInfo> value2; while (true) { FieldInfo[] fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo item in fields) { if (value == null) { value = new List<FieldInfo>(); } value.Add(item); } type2 = type2.BaseType; if (assignableFieldsByObjectType.TryGetValue(type2, out value2)) { break; } bool flag = true; } if (value2 != null) { if (value == null) { value = new List<FieldInfo>(); } value.AddRange(value2); } assignableFieldsByObjectType.Add(type, value); } if (!assignablePropertiesByObjectType.TryGetValue(type, out var value3)) { Type type3 = type; List<PropertyInfo> value4; while (true) { PropertyInfo[] properties = type3.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo item2 in properties) { if (value3 == null) { value3 = new List<PropertyInfo>(); } value3.Add(item2); } type3 = type3.BaseType; if (assignablePropertiesByObjectType.TryGetValue(type3, out value4)) { break; } bool flag2 = true; } if (value4 != null) { if (value3 == null) { value3 = new List<PropertyInfo>(); } value3.AddRange(value4); } assignablePropertiesByObjectType.Add(type, value3); } if (value != null) { foreach (FieldInfo item3 in value) { if (!item3.FieldType.IsSubclassOf(typeof(Object)) && !(item3.FieldType == typeof(Object)) && (!typeof(IEnumerable).IsAssignableFrom(item3.FieldType) || !(item3.FieldType != typeof(string)))) { continue; } if (item3.GetValue(target) is IEnumerable enumerable && !(enumerable is string)) { foreach (object item4 in enumerable) { Object val = (Object)((item4 is Object) ? item4 : null); if (val != (Object)null) { list.Add(val); } } } else { object? value5 = item3.GetValue(target); Object val2 = (Object)((value5 is Object) ? value5 : null); if (val2 != (Object)null) { list.Add(val2); } } } } if (value3 != null) { foreach (PropertyInfo item5 in value3) { string text = (item5.DeclaringType.Name + "." + item5.Name).ToLower(); if (ignoredProperties.Contains(text) || !item5.CanRead || (!item5.PropertyType.IsSubclassOf(typeof(Object)) && !(item5.PropertyType == typeof(Object)) && (!typeof(IEnumerable).IsAssignableFrom(item5.PropertyType) || !(item5.PropertyType != typeof(string)))) || item5.Name == "Item") { continue; } if (target is Material) { Material val3 = (Material)target; if (!val3.HasProperty("_MainTex") && item5.Name == "mainTexture") { continue; } } if (target is Mesh) { Mesh val4 = (Mesh)target; if (meshReadProperties.Contains(item5.Name)) { continue; } } try { if (item5.GetValue(target) is IEnumerable enumerable2 && !(enumerable2 is string)) { foreach (object item6 in enumerable2) { Object val5 = (Object)((item6 is Object) ? item6 : null); if (val5 != (Object)null) { list.Add(val5); } } } else { object? value6 = item5.GetValue(target); Object val6 = (Object)((value6 is Object) ? value6 : null); if (val6 != (Object)null) { list.Add(val6); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Error while calling " + text + ", continuing:")); Plugin.Log.LogWarning((object)ex); } } } if (target is Material) { Material val7 = (Material)target; string[] texturePropertyNames = val7.GetTexturePropertyNames(); foreach (string text2 in texturePropertyNames) { Texture texture = val7.GetTexture(text2); if ((Object)(object)texture != (Object)null) { list.Add((Object)(object)texture); } } } return list; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Error while retrieving object references for " + target.name + " of type " + type.Name + ", continuing:")); Plugin.Log.LogWarning((object)ex2); return list; } } public static void IncrementReferenceCounts(List<Object> references) { foreach (Object reference in references) { int instanceID = reference.GetInstanceID(); referenceTracking.TryGetValue(instanceID, out var value); referenceTracking[instanceID] = (ushort)(value + 1); } } public static void BuildBundleDependencies(string bundleName, Object reference) { if (AssetBundleValid(bundleName) && !(reference == (Object)null) && !bundleTracking.ContainsKey(reference.name.ToLower())) { bundleTracking[reference.name.ToLower()] = bundleName; BuildBundleDependencies(bundleName, GetUnityObjectReferences(reference)); } } public static void BuildBundleDependencies(string bundleName, List<Object> references) { if (!AssetBundleValid(bundleName)) { return; } foreach (Object reference in references) { BuildBundleDependencies(bundleName, reference); } } } } namespace Scoops.rendering { internal class SpongeCustomPass : CustomPass { public static Material posterizationMaterial; public static Shader posterizationShader; public static RTHandle posterizationRT; public override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) posterizationShader = (Shader)Plugin.SpongeAssets.LoadAsset("SpongePosterize"); posterizationMaterial = CoreUtils.CreateEngineMaterial(posterizationShader); posterizationRT = RTHandles.Alloc(Vector2.one, TextureXR.slices, (DepthBits)0, (GraphicsFormat)4, (FilterMode)0, (TextureWrapMode)0, TextureXR.dimension, false, false, true, false, 1, 0f, (MSAASamples)1, false, true, (RenderTextureMemoryless)0, (VRTextureUsage)0, "Posterization Buffer"); } public override void Execute(CustomPassContext ctx) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) CoreUtils.SetRenderTarget(ctx.cmd, posterizationRT, (ClearFlag)1, 0, (CubemapFace)(-1), -1); CoreUtils.DrawFullScreen(ctx.cmd, posterizationMaterial, ctx.propertyBlock, posterizationMaterial.FindPass("ReadColor")); ctx.propertyBlock.SetTexture("_PosterizationBuffer", RTHandle.op_Implicit(posterizationRT)); CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraColorBuffer, (ClearFlag)0, 0, (CubemapFace)(-1), -1); CoreUtils.DrawFullScreen(ctx.cmd, posterizationMaterial, ctx.propertyBlock, posterizationMaterial.FindPass("WriteColor")); } public override void Cleanup() { CoreUtils.Destroy((Object)(object)posterizationMaterial); posterizationRT.Release(); } } } namespace Scoops.patches { [HarmonyPatch] public class AssetBundleSpongePatch { private static IEnumerable<MethodBase> TargetMethods() { return new MethodInfo[8] { AccessTools.Method(typeof(AssetBundle), "LoadFromFile", new Type[1] { typeof(string) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromFile", new Type[2] { typeof(string), typeof(uint) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromFile", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromMemory", new Type[1] { typeof(byte[]) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromMemory", new Type[2] { typeof(byte[]), typeof(uint) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromStream", new Type[1] { typeof(Stream) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromStream", new Type[2] { typeof(Stream), typeof(uint) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromStream", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }, (Type[])null) }; } private static void Postfix(ref AssetBundle __result) { SpongeService.RegisterAssetBundle(__result); } } [HarmonyPatch] public class AssetBundleAsyncSpongePatch { private static IEnumerable<MethodBase> TargetMethods() { return new MethodInfo[8] { AccessTools.Method(typeof(AssetBundle), "LoadFromFileAsync", new Type[1] { typeof(string) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromFileAsync", new Type[2] { typeof(string), typeof(uint) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromFileAsync", new Type[3] { typeof(string), typeof(uint), typeof(ulong) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromMemoryAsync", new Type[1] { typeof(byte[]) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromMemoryAsync", new Type[2] { typeof(byte[]), typeof(uint) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromStreamAsync", new Type[1] { typeof(Stream) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromStreamAsync", new Type[2] { typeof(Stream), typeof(uint) }, (Type[])null), AccessTools.Method(typeof(AssetBundle), "LoadFromStreamAsync", new Type[3] { typeof(Stream), typeof(uint), typeof(uint) }, (Type[])null) }; } private static void Postfix(ref AssetBundleCreateRequest __result) { if (((AsyncOperation)__result).isDone) { SpongeService.RegisterAssetBundle(__result.assetBundle); return; } ((AsyncOperation)__result).completed += delegate(AsyncOperation asyncOperation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SpongeService.RegisterAssetBundle(((AssetBundleCreateRequest)asyncOperation).assetBundle); }; } } [HarmonyPatch] public class AssetBundleLoadSpongePatch { private static IEnumerable<MethodBase> TargetMethods() { return from x in AccessTools.GetDeclaredMethods(typeof(AssetBundle)) where x.Name.Equals("LoadAsset") where !x.IsGenericMethod select x; } private static void Postfix(ref AssetBundle __instance, ref Object __result) { SpongeService.ObjectLoaded(__instance, __result); } } [HarmonyPatch] public class AssetBundleLoadAsyncSpongePatch { private static IEnumerable<MethodBase> TargetMethods() { return from x in AccessTools.GetDeclaredMethods(typeof(AssetBundle)) where x.Name.Equals("LoadAssetAsync") where !x.IsGenericMethod select x; } private static void Postfix(ref AssetBundle __instance, ref AssetBundleRequest __result) { AssetBundle bundle = __instance; if (((AsyncOperation)__result).isDone) { SpongeService.ObjectLoaded(bundle, __result.asset); return; } ((AsyncOperation)__result).completed += delegate(AsyncOperation asyncOperation) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) SpongeService.ObjectLoaded(bundle, ((AssetBundleRequest)asyncOperation).asset); }; } } [HarmonyPatch] public class AssetBundleLoadMultipleSpongePatch { private static IEnumerable<MethodBase> TargetMethods() { return from x in AccessTools.GetDeclaredMethods(typeof(AssetBundle)) where x.Name.Equals("LoadAllAssets") || x.Name.Equals("LoadAssetWithSubAssets") where !x.IsGenericMethod select x; } private static void Postfix(ref AssetBundle __instance, ref Object[] __result) { if (__result != null) { Object[] array = __result; foreach (Object obj in array) { SpongeService.ObjectLoaded(__instance, obj); } } } } [HarmonyPatch] public class AssetBundleLoadMultipleAsyncSpongePatch { private static IEnumerable<MethodBase> TargetMethods() { return from x in AccessTools.GetDeclaredMethods(typeof(AssetBundle)) where x.Name.Equals("LoadAllAssetsAsync") || x.Name.Equals("LoadAssetWithSubAssetsAsync") where !x.IsGenericMethod select x; } private static void Postfix(ref AssetBundle __instance, ref AssetBundleRequest __result) { AssetBundle bundle = __instance; if (((AsyncOperation)__result).isDone) { Object[] allAssets = __result.allAssets; foreach (Object obj in allAssets) { SpongeService.ObjectLoaded(bundle, obj); } return; } ((AsyncOperation)__result).completed += delegate(AsyncOperation asyncOperation) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) Object[] allAssets2 = ((AssetBundleRequest)asyncOperation).allAssets; foreach (Object obj2 in allAssets2) { SpongeService.ObjectLoaded(bundle, obj2); } }; } } [HarmonyPatch(typeof(FoliageDetailDistance))] public class FoliageDetailDistanceSpongePatch { [HarmonyPatch("Update")] [HarmonyPrefix] private static bool FoliageDetailDistance_Update(ref FoliageDetailDistance __instance) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.localPlayerTransform == (Object)null) { return false; } if (__instance.updateInterval >= 0f) { FoliageDetailDistance obj = __instance; obj.updateInterval -= Time.deltaTime; } else if (__instance.bushIndex < __instance.allBushRenderers.Count) { if ((Object)(object)__instance.allBushRenderers[__instance.bushIndex] == (Object)null) { return false; } Vector3 val = __instance.localPlayerTransform.position - ((Component)__instance.allBushRenderers[__instance.bushIndex]).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 5625f) { if ((Object)(object)((Renderer)__instance.allBushRenderers[__instance.bushIndex]).sharedMaterial != (Object)(object)__instance.lowDetailMaterial) { ((Renderer)__instance.allBushRenderers[__instance.bushIndex]).sharedMaterial = __instance.lowDetailMaterial; } } else if ((Object)(object)((Renderer)__instance.allBushRenderers[__instance.bushIndex]).sharedMaterial != (Object)(object)__instance.highDetailMaterial) { ((Renderer)__instance.allBushRenderers[__instance.bushIndex]).sharedMaterial = __instance.highDetailMaterial; } FoliageDetailDistance obj2 = __instance; obj2.bushIndex++; } else { __instance.bushIndex = 0; __instance.updateInterval = 1f; } return false; } } [HarmonyPatch(typeof(HDRenderPipeline))] [HarmonyPatch("RecordRenderGraph")] public static class HDRenderPipeline_RecordRenderGraph_Patch { private static readonly List<CodeInstruction> instructionsToInsert = new List<CodeInstruction> { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(HDRenderPipeline), "m_RenderGraph")), new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Ldloc_S, (object)8), new CodeInstruction(OpCodes.Ldloca_S, (object)13), new CodeInstruction(OpCodes.Ldloc_3, (object)null), new CodeInstruction(OpCodes.Ldloc_2, (object)null), new CodeInstruction(OpCodes.Ldc_I4_7, (object)null), new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Ldarg_S, (object)4), CodeInstruction.Call(typeof(HDRenderPipeline), "RenderCustomPass", (Type[])null, (Type[])null), new CodeInstruction(OpCodes.Pop, (object)null), new CodeInstruction(OpCodes.Ldarg_0, (object)null) }; private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Call && CodeInstructionExtensions.Calls(list[i], AccessTools.Method(typeof(HDRenderPipeline), "RenderSubsurfaceScattering", (Type[])null, (Type[])null)) && list[i + 1].opcode == OpCodes.Ldarg_0) { num = i + 2; break; } } if (num != -1) { list.InsertRange(num, instructionsToInsert); } return list; } } public static class InputActionSpongePatches { public static PlayerActions Actions; public static void Init() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown Actions = new PlayerActions(); Actions.Enable(); InputSystem.settings.SetInternalFeatureFlag("USE_OPTIMIZED_CONTROLS", true); InputSystem.settings.SetInternalFeatureFlag("USE_READ_VALUE_CACHING", true); } [HarmonyPatch(typeof(DeferBindingResolutionWrapper))] [HarmonyPatch("Dispose")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> DeferBindingResolutionWrapper_Dispose_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 2; i++) { if (CodeInstructionExtensions.LoadsField(list[i], AccessTools.Field(typeof(InputActionMap), "s_DeferBindingResolution"), false) && list[i + 1].opcode == OpCodes.Brtrue_S && CodeInstructionExtensions.Calls(list[i + 2], AccessTools.Method(typeof(InputActionState), "DeferredResolutionOfBindings", (Type[])null, (Type[])null))) { num = i; break; } } if (num != -1) { list.RemoveRange(num, 3); } return list; } [HarmonyPatch(typeof(PlayerControllerB))] [HarmonyPatch("Look_performed")] [HarmonyPrefix] private static bool PlayerControllerB_Look_performed(ref PlayerControllerB __instance, ref CallbackContext context) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((!((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject)) && !__instance.isTestingPlayer) { return false; } if (__instance.quickMenuManager.isMenuOpen || __instance.inSpecialMenu) { Vector2 val = ((CallbackContext)(ref context)).ReadValue<Vector2>(); if (((Vector2)(ref val)).magnitude > 0.001f) { Cursor.visible = true; } return false; } StartOfRound.Instance.localPlayerUsingController = !InputControlPath.MatchesPrefix("<Mouse>", ((CallbackContext)(ref context)).control); return false; } [HarmonyPatch(typeof(PlayerControllerB))] [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> PlayerControllerB_Awake_Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Newobj && CodeInstructionExtensions.StoresField(list[i + 1], AccessTools.Field(typeof(PlayerControllerB), "playerActions"))) { num = i; break; } } if (num != -1) { list.RemoveAt(num); list.Insert(num, new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(InputActionSpongePatches), "Actions"))); } return list; } [HarmonyPatch(typeof(PlayerControllerB))] [HarmonyPatch("OnDisable")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> PlayerControllerB_OnDisable_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 6; i++) { if (list[i].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[i + 1], AccessTools.Field(typeof(PlayerControllerB), "playerActions"), false) && list[i + 2].opcode == OpCodes.Callvirt && list[i + 3].opcode == OpCodes.Stloc_1 && list[i + 4].opcode == OpCodes.Ldloca_S && CodeInstructionExtensions.Calls(list[i + 5], AccessTools.Method(typeof(MovementActions), "Enable", (Type[])null, (Type[])null))) { num = i; break; } } if (num != -1) { list.RemoveRange(num, 6); } num = -1; for (int j = 0; j < list.Count - 6; j++) { if (list[j].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[j + 1], AccessTools.Field(typeof(PlayerControllerB), "playerActions"), false) && list[j + 2].opcode == OpCodes.Callvirt && list[j + 3].opcode == OpCodes.Stloc_1 && list[j + 4].opcode == OpCodes.Ldloca_S && CodeInstructionExtensions.Calls(list[j + 5], AccessTools.Method(typeof(MovementActions), "Disable", (Type[])null, (Type[])null))) { num = j; break; } } if (num != -1) { List<Label> labels = list[num].labels; list.RemoveRange(num, 6); list[num].labels.AddRange(labels); } return list; } [HarmonyPatch(typeof(DisableMouseInMenu))] [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> DisableMouseInMenu_Awake_Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Newobj && CodeInstructionExtensions.StoresField(list[i + 1], AccessTools.Field(typeof(DisableMouseInMenu), "actions"))) { num = i; break; } } if (num != -1) { list.RemoveAt(num); list.Insert(num, new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(InputActionSpongePatches), "Actions"))); } return list; } [HarmonyPatch(typeof(HUDManager))] [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HUDManager_Awake_Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Newobj && CodeInstructionExtensions.StoresField(list[i + 1], AccessTools.Field(typeof(HUDManager), "playerActions"))) { num = i; break; } } if (num != -1) { list.RemoveAt(num); list.Insert(num, new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(InputActionSpongePatches), "Actions"))); } return list; } [HarmonyPatch(typeof(HUDManager))] [HarmonyPatch("OnDisable")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HUDManager_OnDisable_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 6; i++) { if (list[i].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[i + 1], AccessTools.Field(typeof(HUDManager), "playerActions"), false) && list[i + 2].opcode == OpCodes.Callvirt && list[i + 3].opcode == OpCodes.Stloc_0 && list[i + 4].opcode == OpCodes.Ldloca_S && CodeInstructionExtensions.Calls(list[i + 5], AccessTools.Method(typeof(MovementActions), "Disable", (Type[])null, (Type[])null))) { num = i; break; } } if (num != -1) { list.RemoveRange(num, 6); } return list; } [HarmonyPatch(typeof(InitializeGame))] [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> InitializeGame_Awake_Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Newobj && CodeInstructionExtensions.StoresField(list[i + 1], AccessTools.Field(typeof(InitializeGame), "playerActions"))) { num = i; break; } } if (num != -1) { list.RemoveAt(num); list.Insert(num, new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(InputActionSpongePatches), "Actions"))); } return list; } [HarmonyPatch(typeof(InitializeGame))] [HarmonyPatch("OnDisable")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> InitializeGame_OnDisable_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 6; i++) { if (list[i].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[i + 1], AccessTools.Field(typeof(InitializeGame), "playerActions"), false) && list[i + 2].opcode == OpCodes.Callvirt && list[i + 3].opcode == OpCodes.Stloc_0 && list[i + 4].opcode == OpCodes.Ldloca_S && CodeInstructionExtensions.Calls(list[i + 5], AccessTools.Method(typeof(MovementActions), "Disable", (Type[])null, (Type[])null))) { num = i; break; } } if (num != -1) { list.RemoveRange(num, 6); } return list; } [HarmonyPatch(typeof(ShipBuildModeManager))] [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ShipBuildModeManager_Awake_Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Newobj && CodeInstructionExtensions.StoresField(list[i + 1], AccessTools.Field(typeof(ShipBuildModeManager), "playerActions"))) { num = i; break; } } if (num != -1) { list.RemoveAt(num); list.Insert(num, new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(InputActionSpongePatches), "Actions"))); } return list; } [HarmonyPatch(typeof(ShipBuildModeManager))] [HarmonyPatch("OnDisable")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ShipBuildModeManager_OnDisable_Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 6; i++) { if (list[i].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[i + 1], AccessTools.Field(typeof(ShipBuildModeManager), "playerActions"), false) && list[i + 2].opcode == OpCodes.Callvirt && list[i + 3].opcode == OpCodes.Stloc_0 && list[i + 4].opcode == OpCodes.Ldloca_S && CodeInstructionExtensions.Calls(list[i + 5], AccessTools.Method(typeof(MovementActions), "Disable", (Type[])null, (Type[])null))) { num = i; break; } } if (num != -1) { list.RemoveRange(num, 6); } return list; } [HarmonyPatch(typeof(Terminal))] [HarmonyPatch("Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Terminal_Awake_Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Newobj && CodeInstructionExtensions.StoresField(list[i + 1], AccessTools.Field(typeof(Terminal), "playerActions"))) { num = i; break; } } if (num != -1) { list.RemoveAt(num); list.Insert(num, new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(InputActionSpongePatches), "Actions"))); } return list; } } [HarmonyPatch(typeof(ManualCameraRenderer))] public class ManualCameraRendererSpongePatch { [HarmonyPatch("Update")] [HarmonyPostfix] private static void ManualCameraRenderer_Update(ref ManualCameraRenderer __instance) { if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null || (Object)(object)NetworkManager.Singleton == (Object)null || !__instance.overrideCameraForOtherUse) { return; } if ((Object)(object)__instance.mesh != (Object)null && !MeshVisible(GameNetworkManager.Instance.localPlayerController.gameplayCamera, __instance.mesh)) { ((Behaviour)__instance.cam).enabled = false; } else if (__instance.renderAtLowerFramerate) { ((Behaviour)__instance.cam).enabled = false; ManualCameraRenderer obj = __instance; obj.elapsed += Time.deltaTime; if (__instance.elapsed > 1f / __instance.fps) { __instance.elapsed = 0f; __instance.cam.Render(); } } else { ((Behaviour)__instance.cam).enabled = true; } } [HarmonyPatch("MeetsCameraEnabledConditions")] [HarmonyAfter(new string[] { "Zaggy1024.OpenBodyCams" })] [HarmonyPostfix] private static void ManualCameraRenderer_MeetsCameraEnabledConditions(ref ManualCameraRenderer __instance, ref bool __result, PlayerControllerB player) { if ((Object)(object)__instance.mesh != (Object)null && !MeshVisible(player.gameplayCamera, __instance.mesh)) { __result = false; } if ((Object)(object)__instance == (Object)(object)StartOfRound.Instance.mapScreen && !__result && !((Object)(object)CameraService.MainTerminal == (Object)null) && (Object)(object)CameraService.MainTerminal.displayingPersistentImage == (Object)(object)__instance.mapCamera.activeTexture && ((Behaviour)CameraService.MainTerminal.terminalUIScreen).isActiveAndEnabled) { __result = true; } } private static bool MeshVisible(Camera camera, MeshRenderer mesh) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Plane[] array = GeometryUtility.CalculateFrustumPlanes(camera); if (Object.op_Implicit((Object)(object)((Component)mesh).GetComponent<Collider>())) { return GeometryUtility.TestPlanesAABB(array, ((Component)mesh).GetComponent<Collider>().bounds); } if (Object.op_Implicit((Object)(object)((Component)mesh).GetComponent<Renderer>())) { return GeometryUtility.TestPlanesAABB(array, ((Component)mesh).GetComponent<Renderer>().bounds); } return !array.Any((Plane plane) => ((Plane)(ref plane)).GetDistanceToPoint(((Component)mesh).transform.position) < 0f); } } [HarmonyPatch(typeof(PlayerControllerB))] public class PlayerControllerBSpongePatch { [HarmonyPatch("ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PlayerControllerB_ConnectClientToPlayerObject(ref PlayerControllerB __instance) { CameraService.ApplyPlayerCameraPatch(__instance); } } [HarmonyPatch(typeof(RoundManager))] public class RoundManagerSpongePatch { [HarmonyPatch("FinishGeneratingLevel")] [HarmonyPostfix] private static void RoundManager_FinishGeneratingLevel(ref RoundManager __instance) { SpongeService.DungeonLoaded(__instance.dungeonGenerator.Generator); if (Config.changeLightFadeDistance.Value) { LightService.UpdateAllLights(); } } } [HarmonyPatch(typeof(StartOfRound))] public class StartOfRoundSpongePatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartOfRound_Start(ref StartOfRound __instance) { SpongeService.Initialize(); if (Config.fixCameraSettings.Value && CameraService.Init()) { CameraService.ApplyCameraFixes(); } if (Config.removePosterizationShader.Value) { CameraService.DisablePosterization(); } } [HarmonyPatch("PassTimeToNextDay")] [HarmonyPostfix] private static void StartOfRound_PassTimeToNextDay(ref StartOfRound __instance) { if (SpongeService.enabled) { SpongeService.ApplySponge(); } } [HarmonyPatch("SwitchCamera")] [HarmonyPostfix] private static void StartOfRound_SwitchCamera(ref StartOfRound __instance, Camera newCamera) { if (Config.removePosterizationShader.Value && Config.useCustomShader.Value) { CameraService.UpdateCamera(newCamera); } } [HarmonyPatch(typeof(HUDManager))] [HarmonyPatch("AddTextToChatOnServer")] [HarmonyPrefix] private static bool HUDManager_AddTextToChatOnServer(ref HUDManager __instance, string chatMessage, int playerId) { if (chatMessage.ToLower() == "/sponge help") { __instance.AddChatMessage("'/sponge': Run Sponge.\n'/sponge evaluate': Run Sponge Evaluation only.\n'/sponge clean': Run Sponge Cleanup only.\n'/sponge toggle': Toggle Sponge daily auto activate.\n'/sponge modelcheck': Ask Sponge for a readout of the meshes currently rendering.\n'/sponge texturecheck': Ask Sponge for a readout of the textures currently rendering.\n", ""); return false; } if (chatMessage.ToLower() == "/sponge") { __instance.AddChatMessage("Applying Sponge.", ""); SpongeService.ApplySponge(); return false; } if (chatMessage.ToLower() == "/sponge evaluate") { __instance.AddChatMessage("Applying Sponge evaluate.", ""); SpongeService.ApplySponge(SpongeMode.Evaluate); return false; } if (chatMessage.ToLower() == "/sponge clean") { __instance.AddChatMessage("Applying Sponge cleanup.", ""); SpongeService.ApplySponge(SpongeMode.Clean); return false; } i