Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RepoOptimizerforPentium v1.2.0
RepoOptimizer.dll
Decompiled 38 minutes agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 RepoOptimizer { [BepInPlugin("REPOOptimizer.Performance", "REPO Optimizer", "1.2.0")] public class Plugin : BaseUnityPlugin { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private class MemStatus { public uint dwLength = (uint)Marshal.SizeOf(typeof(MemStatus)); public uint dwMemoryLoad; public ulong ullTotalPhys; public ulong ullAvailPhys; public ulong ullTotalPageFile; public ulong ullAvailPageFile; public ulong ullTotalVirtual; public ulong ullAvailVirtual; public ulong ullAvailExtendedVirtual; } private static Plugin Instance; private static ConfigEntry<string> cPreset; private static ConfigEntry<bool> cEnabled; private static ConfigEntry<bool> cDebugLog; private static ConfigEntry<float> cScanInterval; private static ConfigEntry<float> cPauseAfterScene; private static ConfigEntry<string> cExcludeObjects; private static ConfigEntry<bool> cParticles; private static ConfigEntry<string> cParticleExclude; private static ConfigEntry<float> cParticleScanInterval; private static ConfigEntry<bool> cWaterParticles; private static ConfigEntry<bool> cHideWater; private static ConfigEntry<bool> cWaterOnLow; private static ConfigEntry<string> cWaterPartKw; private static ConfigEntry<string> cWaterKw; private static ConfigEntry<bool> cDistRenderers; private static ConfigEntry<bool> cDistLights; private static ConfigEntry<bool> cDistAudio; private static ConfigEntry<bool> cAnimCull; private static ConfigEntry<float> cRenderDist; private static ConfigEntry<float> cLightDist; private static ConfigEntry<float> cAudioDist; private static ConfigEntry<int> cChunk; private static ConfigEntry<string> cExcludeLayers; private static ConfigEntry<int> cShaderLevel; private static ConfigEntry<int> cGlobalLod; private static ConfigEntry<string> cShaderExclude; private static ConfigEntry<string> cPostTypes; private static ConfigEntry<bool> cLogShaders; private static ConfigEntry<bool> cPhysics; private static ConfigEntry<float> cSleepThreshold; private static ConfigEntry<int> cFpsLimit; private static ConfigEntry<int> cVsync; private static ConfigEntry<bool> cShowFps; private static ConfigEntry<KeyCode> cFpsKey; private static ConfigEntry<bool> cShadowsOff; private static ConfigEntry<bool> cAnisoOff; private static ConfigEntry<bool> cSimpleSkin; private static ConfigEntry<bool> cReflProbesOff; private static ConfigEntry<float> cShadowDist; private static ConfigEntry<float> cLodBias; private static ConfigEntry<float> cCameraFar; private static ConfigEntry<int> cTexLimit; private static ConfigEntry<int> cAntiAlias; private static ConfigEntry<int> cPixelLights; private static ConfigEntry<bool> cMemGuard; private static ConfigEntry<bool> cMemCleanup; private static ConfigEntry<int> cLowMemMb; private static ConfigEntry<string> cTempKw; private static ConfigEntry<bool> cCartHud; private static ConfigEntry<bool> cEnemyFix; private static ConfigEntry<float> cHudOffsetY; private static ConfigEntry<string> cHudLabel; private static ConfigEntry<KeyCode> cRenderKey; private static ConfigEntry<KeyCode> cMuteKey; private static ConfigEntry<bool> cRenderCtrl; private static ConfigEntry<bool> cMuteCtrl; private static ConfigEntry<string> cMuteTarget; private static ConfigEntry<string> cVoiceKw; private static ConfigEntry<KeyCode> cDumpKey; private static ConfigEntry<KeyCode> cInspectKey; private static ConfigEntry<bool> cSpawnLog; private static List<string> exObjects = new List<string>(); private static List<string> exParticles = new List<string>(); private static List<string> exShaders = new List<string>(); private static List<string> postTypes = new List<string>(); private static List<string> waterKw = new List<string>(); private static List<string> waterPartKw = new List<string>(); private static List<string> tempKw = new List<string>(); private static List<string> voiceKw = new List<string>(); private static readonly HashSet<int> exLayers = new HashSet<int>(); private static readonly List<string> builtinEx = new List<string> { "backdrop", "skybox", "moon" }; private static readonly Dictionary<int, bool> particleExCache = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> excludeCache = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> textShaderCache = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> waterCache = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> waterShaderCache = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> waterPartCache = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> voiceCache = new Dictionary<int, bool>(); private static int camMask = -1; private static bool pressure; private static float spawnWin; private static int spawnCnt; private static float cartValue = -1f; private static readonly HashSet<ParticleSystem> killedParticles = new HashSet<ParticleSystem>(); private Culler<Renderer> renderCuller; private Culler<Light> lightCuller; private Culler<AudioSource> audioCuller; private readonly HashSet<Rigidbody> sleepDone = new HashSet<Rigidbody>(); private readonly HashSet<Animator> animDone = new HashSet<Animator>(); private readonly List<Material> mats = new List<Material>(); private readonly Dictionary<Material, Shader> originalShaders = new Dictionary<Material, Shader>(); private readonly HashSet<Material> matSeen = new HashSet<Material>(); private readonly Dictionary<string, Shader> shaderCache = new Dictionary<string, Shader>(); private readonly HashSet<Renderer> waterHidden = new HashSet<Renderer>(); private readonly Dictionary<Camera, int> camMasks = new Dictionary<Camera, int>(); private readonly HashSet<AudioSource> mutedSources = new HashSet<AudioSource>(); private readonly Dictionary<int, float> zeroSince = new Dictionary<int, float>(); private readonly Dictionary<int, int> killTries = new Dictionary<int, int>(); private int matIdx; private int appliedShaderLevel; private int scanCount; private int crumbLines; private bool warnedNoShader; private bool loggedShadersThisScene; private bool hotkeyBroken; private float scanTimer = 1.5f; private float particleTimer = 1f; private float pauseUntil; private float burstUntil; private float camRetry; private float frameMs = 16f; private float memTimer; private float lastCleanup = -999f; private float renderOffTimer; private float muteTimer; private float savedVolume = 1f; private bool renderOff; private bool muted; private Camera cam; private StreamWriter sw; private float cartTimer; private bool cartTypesSearched; private bool cartErrLogged; private Type cartType; private Type valuableType; private FieldInfo cartDirectField; private FieldInfo valuableValueField; private GUIStyle hudStyle; private float enemyTimer; private bool enemyTypesSearched; private bool enemyErrLogged; private bool enemyNotReadyLogged; private bool photonSearched; private Type healthType; private FieldInfo hpField; private FieldInfo deadField; private MethodInfo killMethod; private PropertyInfo masterProp; private const string CartTypeName = "PhysGrabCart"; private const string ValuableTypeName = "ValuableObject"; private static readonly string[] CartFieldNames = new string[1] { "haulCurrent" }; private static readonly string[] ValuableFieldNames = new string[2] { "dollarValueCurrent", "dollarValueOriginal" }; private const string HealthTypeName = "EnemyHealth"; private static readonly string[] HpFieldNames = new string[2] { "healthCurrent", "currentHealth" }; private static readonly string[] DeadFieldNames = new string[2] { "dead", "isDead" }; private static readonly string[] KillMethodNames = new string[2] { "Death", "Die" }; private const float ZeroHpGraceSeconds = 3f; private static float DistMul { get { if (!pressure || !cMemGuard.Value) { return 1f; } return 0.5f; } } private static bool WaterHideActive { get { if (cEnabled.Value) { if (!cHideWater.Value) { if (cWaterOnLow.Value && pressure) { return cMemGuard.Value; } return false; } return true; } return false; } } private void BindConfig() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_07d1: Unknown result type (might be due to invalid IL or missing references) //IL_07db: Expected O, but got Unknown cPreset = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Preset", "Custom", new ConfigDescription("Ready-made setting sets. Safe = distance culling only (for troubleshooting), Low = weak PC, Potato = very weak PC. Pick one and save: the mod writes the values into the config below and switches back to Custom. Restart the game afterwards.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Custom", "Safe", "Low", "Potato" }), Array.Empty<object>())); cEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch for the whole mod."); cScanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ScanIntervalSeconds", 5f, "How often the mod looks for new objects in the scene (seconds). Higher = lighter, but new objects are handled later."); cPauseAfterScene = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PauseAfterSceneChangeSeconds", 1.5f, "The mod does nothing for this long after a scene change (level load, extraction, shop). Protects against crashes during transitions."); cExcludeObjects = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ExcludeObjects", "player,valuable,camera,flashlight,truck,cart,extraction,enemy,map,money,haul,quota,display,screen", "Comma-separated words. Objects whose name (or root object name) contains any of them are never hidden by distance culling or shader replacement."); cDebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", false, "Verbose log of the mod's steps (also written to BepInEx/config/REPO_Optimizer/session.log). For troubleshooting only."); cParticles = ((BaseUnityPlugin)this).Config.Bind<bool>("Particles", "RemoveAllParticles", true, "Remove all particle effects (blocks them from playing and disables their rendering)."); cParticleExclude = ((BaseUnityPlugin)this).Config.Bind<string>("Particles", "Exclude", "enemy", "Comma-separated words. Particles on objects with these words in the name are kept."); cParticleScanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Particles", "ScanIntervalSeconds", 1.5f, "How often to check for particles that start by themselves."); cWaterParticles = ((BaseUnityPlugin)this).Config.Bind<bool>("Water", "RemoveWaterParticles", true, "Remove water particles (splashes, bubbles, foam, ripples). The water itself stays."); cWaterPartKw = ((BaseUnityPlugin)this).Config.Bind<string>("Water", "ParticleKeywords", "water,splash,bubble,foam,ripple,droplet", "Words in the particle's name (or its three parents) that identify water particles. Use the Inspect key to find exact names."); cHideWater = ((BaseUnityPlugin)this).Config.Bind<bool>("Water", "HideWater", false, "Never render water (matched by keywords below)."); cWaterOnLow = ((BaseUnityPlugin)this).Config.Bind<bool>("Water", "HideWaterOnLowMemory", true, "Do not render water while the low-memory mode is active."); cWaterKw = ((BaseUnityPlugin)this).Config.Bind<string>("Water", "Keywords", "water,liquid,pool", "Words in an object or shader name that identify water."); cDistRenderers = ((BaseUnityPlugin)this).Config.Bind<bool>("Distance", "CullRenderers", true, "Hide models farther than RenderDistance."); cRenderDist = ((BaseUnityPlugin)this).Config.Bind<float>("Distance", "RenderDistance", 60f, "Distance for models (meters)."); cDistLights = ((BaseUnityPlugin)this).Config.Bind<bool>("Distance", "CullLights", true, "Turn off distant lights (directional lights are never touched)."); cLightDist = ((BaseUnityPlugin)this).Config.Bind<float>("Distance", "LightDistance", 40f, "Distance for lights (meters)."); cDistAudio = ((BaseUnityPlugin)this).Config.Bind<bool>("Distance", "MuteFarAudio", true, "Mute distant 3D sounds (2D sounds and voice chat are never touched)."); cAudioDist = ((BaseUnityPlugin)this).Config.Bind<float>("Distance", "AudioDistance", 50f, "Distance for sounds (meters)."); cAnimCull = ((BaseUnityPlugin)this).Config.Bind<bool>("Distance", "AnimatorCulling", false, "Animators skip bone updates while not visible. Can break enemy hitboxes, so it is off by default."); cChunk = ((BaseUnityPlugin)this).Config.Bind<int>("Distance", "ObjectsPerFrame", 150, "How many objects of each type are checked per frame. Lower = lighter, but slower reaction."); cExcludeLayers = ((BaseUnityPlugin)this).Config.Bind<string>("Distance", "ExcludeLayers", "map", "Comma-separated Unity layer names whose objects are never hidden by distance (needed for the map). Layer names are listed in dump.txt."); cShaderLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Shaders", "Level", 1, "0 = off. 1 = disable post-processing only. 2 = also replace shaders with simple ones. 3 = almost everything unlit (picture becomes much simpler)."); cShaderExclude = ((BaseUnityPlugin)this).Config.Bind<string>("Shaders", "ExcludeShaders", "ui/,textmeshpro,tmp_,sprites/,skybox,hidden/,particles/,unlit/,mobile/,legacy shaders/diffuse", "Shaders with these words in the name are never replaced."); cLogShaders = ((BaseUnityPlugin)this).Config.Bind<bool>("Shaders", "LogShaderList", false, "Print the list of shaders used in the scene to the log."); cGlobalLod = ((BaseUnityPlugin)this).Config.Bind<int>("Shaders", "GlobalMaximumLOD", 0, "Shader.globalMaximumLOD. 0 = do not touch. For example 200 or 300 simplifies shaders that support LOD."); cPostTypes = ((BaseUnityPlugin)this).Config.Bind<string>("Shaders", "PostProcessTypes", "PostProcessVolume,PostProcessLayer", "Names of post-processing components that are disabled when Level >= 1."); cPhysics = ((BaseUnityPlugin)this).Config.Bind<bool>("Physics", "SleepFaster", false, "Put idle rigidbodies to sleep faster. Saves CPU but may cause odd item behaviour. Off by default."); cSleepThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "SleepThreshold", 0.05f, "Sleep threshold (Unity default is 0.005). Higher = sleeps sooner."); cFpsLimit = ((BaseUnityPlugin)this).Config.Bind<int>("FPS", "FpsLimit", 0, "FPS limit. 0 = do not touch."); cVsync = ((BaseUnityPlugin)this).Config.Bind<int>("FPS", "VSync", -1, "-1 = do not touch, 0 = off, 1 = on."); cShowFps = ((BaseUnityPlugin)this).Config.Bind<bool>("FPS", "ShowCounter", true, "Show an FPS / frame time counter in the corner."); cFpsKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FPS", "ToggleCounterKey", (KeyCode)290, "Key that shows / hides the counter."); cShadowsOff = ((BaseUnityPlugin)this).Config.Bind<bool>("Quality", "ShadowsOff", false, "Turn shadows off completely. One of the biggest FPS gains."); cShadowDist = ((BaseUnityPlugin)this).Config.Bind<float>("Quality", "ShadowDistance", 0f, "Shadow distance in meters. 0 = do not touch. For example 15-25."); cTexLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "TextureQualityDrop", 0, "Lower texture resolution: 0 = do not touch, 1 = half, 2 = quarter. Saves a lot of memory."); cAntiAlias = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "AntiAliasing", -1, "-1 = do not touch, 0 = off, 2/4/8 = level."); cAnisoOff = ((BaseUnityPlugin)this).Config.Bind<bool>("Quality", "AnisotropicOff", false, "Disable anisotropic texture filtering."); cLodBias = ((BaseUnityPlugin)this).Config.Bind<float>("Quality", "LodBias", 0f, "If above 0, caps QualitySettings.lodBias (lower = simpler models sooner). For example 0.5. 0 = do not touch."); cPixelLights = ((BaseUnityPlugin)this).Config.Bind<int>("Quality", "PixelLightCount", -1, "Max pixel lights per object. -1 = do not touch, for example 1 or 2."); cSimpleSkin = ((BaseUnityPlugin)this).Config.Bind<bool>("Quality", "OneBoneSkinning", false, "Simpler mesh animation (1 bone per vertex). Lighter, slightly rougher animation."); cReflProbesOff = ((BaseUnityPlugin)this).Config.Bind<bool>("Quality", "RealtimeReflectionsOff", false, "Disable realtime reflection probes."); cCameraFar = ((BaseUnityPlugin)this).Config.Bind<float>("Quality", "CameraFarClip", 0f, "Camera far clip distance in meters. 0 = do not touch. For example 150."); cMemGuard = ((BaseUnityPlugin)this).Config.Bind<bool>("MemoryGuard", "Enabled", true, "When free memory is low, switch to a lite mode: all particles blocked, distances halved, water and temporary effects not rendered."); cLowMemMb = ((BaseUnityPlugin)this).Config.Bind<int>("MemoryGuard", "LowMemoryMB", 900, "Free memory (MB) below which the lite mode turns on. It turns off again at +300 MB."); cMemCleanup = ((BaseUnityPlugin)this).Config.Bind<bool>("MemoryGuard", "CleanupOnLowMemory", true, "Unload unused assets when the lite mode turns on (a short hitch, at most once per 90 s)."); cTempKw = ((BaseUnityPlugin)this).Config.Bind<string>("MemoryGuard", "TempEffectKeywords", "splash,ripple,gib,debris,chunk,spark,smoke,drip,droplet,blood,fx,effect,bubble,foam", "In lite mode, freshly spawned objects with these words in the name are not rendered."); cCartHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Hud", "CartValue", true, "Show a line under the quota with the total value of everything in the cart."); cHudOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Hud", "OffsetY", 175f, "Vertical position of the line (pixels at 768p height, scaled)."); cHudLabel = ((BaseUnityPlugin)this).Config.Bind<string>("Hud", "Label", "In cart:", "Text of the line."); cEnemyFix = ((BaseUnityPlugin)this).Config.Bind<bool>("EnemyFix", "KillZeroHpEnemies", true, "If an enemy sits at 0 HP without dying (for example after being thrown into a pit), finish it. Host only."); cRenderKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "RenderNothingKey", (KeyCode)106, "Toggles rendering off completely (nothing is drawn: no enemies, no level). Press again to restore."); cRenderCtrl = ((BaseUnityPlugin)this).Config.Bind<bool>("Hotkeys", "RenderNothingNeedsCtrl", false, "Require Ctrl to be held (avoids triggering while typing in chat)."); cMuteKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Mute", "MuteKey", (KeyCode)109, "Toggles muting everyone / everything you hear. Press again to restore."); cMuteCtrl = ((BaseUnityPlugin)this).Config.Bind<bool>("Mute", "MuteNeedsCtrl", false, "Require Ctrl to be held (avoids triggering while typing in chat)."); cMuteTarget = ((BaseUnityPlugin)this).Config.Bind<string>("Mute", "Target", "Everything", new ConfigDescription("Everything = silence all game audio. VoicesOnly = only audio sources whose name matches VoiceKeywords.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Everything", "VoicesOnly" }), Array.Empty<object>())); cVoiceKw = ((BaseUnityPlugin)this).Config.Bind<string>("Mute", "VoiceKeywords", "voice,tts,speech", "Words in an audio source name (or its parents) that identify voice chat. Used only with Target = VoicesOnly."); cDumpKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Debug", "ClassDumpKey", (KeyCode)291, "Writes a list of game classes (enemy, health, cart, voice) to BepInEx/config/REPO_Optimizer/dump.txt."); cInspectKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Debug", "InspectKey", (KeyCode)292, "Aim at an object (within 8 m) and press: writes its renderers, shaders, texts and nearby lights to inspect.txt."); cSpawnLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "SpawnLog", false, "Log the names of spawned objects (up to 25 per second) to session.log. Needs DebugLog."); } private static List<string> Parse(string csv) { return (from s in (csv ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim().ToLowerInvariant() into s where s.Length > 0 select s).ToList(); } private static void ParseLists() { exObjects = Parse(cExcludeObjects.Value); exParticles = Parse(cParticleExclude.Value); exShaders = Parse(cShaderExclude.Value); postTypes = Parse(cPostTypes.Value); waterKw = Parse(cWaterKw.Value); waterPartKw = Parse(cWaterPartKw.Value); tempKw = Parse(cTempKw.Value); voiceKw = Parse(cVoiceKw.Value); ClearCaches(); exLayers.Clear(); List<string> list = Parse(cExcludeLayers.Value); for (int i = 0; i < 32; i++) { string text = LayerMask.LayerToName(i); if (!string.IsNullOrEmpty(text) && list.Contains(text.ToLowerInvariant())) { exLayers.Add(i); } } } private static void ClearCaches() { particleExCache.Clear(); excludeCache.Clear(); textShaderCache.Clear(); waterCache.Clear(); waterShaderCache.Clear(); waterPartCache.Clear(); voiceCache.Clear(); } private static bool NameHas(Component c, List<string> list) { if (list.Count == 0 || (Object)(object)c == (Object)null) { return false; } string text = ((Object)c).name.ToLowerInvariant(); string text2 = ((Object)c.transform.root).name.ToLowerInvariant(); foreach (string item in list) { if (text.Contains(item) || text2.Contains(item)) { return true; } } return false; } private static bool ListHas(string name, List<string> list) { string text = name.ToLowerInvariant(); foreach (string item in list) { if (text.Contains(item)) { return true; } } return false; } private static bool Excluded(Component c) { if ((Object)(object)c == (Object)null) { return false; } int instanceID = ((Object)c).GetInstanceID(); if (!excludeCache.TryGetValue(instanceID, out var value)) { value = NameHas(c, exObjects) || NameHas(c, builtinEx); excludeCache[instanceID] = value; } return value; } private static bool IsTextRenderer(Renderer r) { try { Material sharedMaterial = r.sharedMaterial; if ((Object)(object)sharedMaterial == (Object)null) { return false; } Shader shader = sharedMaterial.shader; if ((Object)(object)shader == (Object)null) { return false; } int instanceID = ((Object)shader).GetInstanceID(); if (!textShaderCache.TryGetValue(instanceID, out var value)) { string name = ((Object)shader).name; value = name.IndexOf("TextMeshPro", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("TMP", StringComparison.OrdinalIgnoreCase) >= 0; textShaderCache[instanceID] = value; } return value; } catch { return false; } } private static bool SeenByMainCamera(Renderer r) { if (exLayers.Contains(((Component)r).gameObject.layer)) { return false; } if (camMask == -1) { return true; } return (camMask & (1 << ((Component)r).gameObject.layer)) != 0; } private static bool IsWaterParticle(ParticleSystem ps) { if ((Object)(object)ps == (Object)null || waterPartKw.Count == 0) { return false; } int instanceID = ((Object)ps).GetInstanceID(); if (!waterPartCache.TryGetValue(instanceID, out var value)) { value = false; Transform val = ((Component)ps).transform; for (int i = 0; i < 4; i++) { if (!((Object)(object)val != (Object)null)) { break; } if (value) { break; } value = ListHas(((Object)val).name, waterPartKw); val = val.parent; } waterPartCache[instanceID] = value; } return value; } private static bool IsWaterObject(Component c) { if ((Object)(object)c == (Object)null || waterKw.Count == 0) { return false; } int instanceID = ((Object)c).GetInstanceID(); if (!waterCache.TryGetValue(instanceID, out var value)) { value = ListHas(((Object)c).name, waterKw); waterCache[instanceID] = value; } return value; } private static bool IsWaterRenderer(Renderer r) { if (IsWaterObject((Component)(object)r)) { return true; } try { Material sharedMaterial = r.sharedMaterial; if ((Object)(object)sharedMaterial == (Object)null || (Object)(object)sharedMaterial.shader == (Object)null) { return false; } int instanceID = ((Object)sharedMaterial.shader).GetInstanceID(); if (!waterShaderCache.TryGetValue(instanceID, out var value)) { value = ListHas(((Object)sharedMaterial.shader).name, waterKw); waterShaderCache[instanceID] = value; } return value; } catch { return false; } } private static bool IsVoiceSource(AudioSource a) { if ((Object)(object)a == (Object)null || voiceKw.Count == 0) { return false; } int instanceID = ((Object)a).GetInstanceID(); if (!voiceCache.TryGetValue(instanceID, out var value)) { value = false; Transform val = ((Component)a).transform; for (int i = 0; i < 4; i++) { if (!((Object)(object)val != (Object)null)) { break; } if (value) { break; } value = ListHas(((Object)val).name, voiceKw); val = val.parent; } voiceCache[instanceID] = value; } return value; } private static string[] SplitNames(string s) { return (from x in (s ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select x.Trim() into x where x.Length > 0 select x).ToArray(); } private static FieldInfo FindField(Type t, string name) { Type type = t; while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } private static bool IsNumeric(Type t) { if (!(t == typeof(int)) && !(t == typeof(float)) && !(t == typeof(double)) && !(t == typeof(long))) { return t == typeof(short); } return true; } private static double ToDouble(object v) { try { return Convert.ToDouble(v, CultureInfo.InvariantCulture); } catch { return 0.0; } } private static string FormatMoney(float v) { return ((long)Math.Round(v)).ToString("N0", CultureInfo.InvariantCulture).Replace(',', ' '); } private static string OutDir() { string text = Path.Combine(Paths.ConfigPath, "REPO_Optimizer"); Directory.CreateDirectory(text); return text; } private static void ApplyPresetIfNeeded() { string value = cPreset.Value; if (!(value == "Custom")) { cPreset.Value = "Custom"; if (value == "Safe") { cParticles.Value = false; cWaterParticles.Value = false; cDistRenderers.Value = true; cRenderDist.Value = 70f; cDistLights.Value = false; cDistAudio.Value = false; cAnimCull.Value = false; cShaderLevel.Value = 0; cPhysics.Value = false; cShadowsOff.Value = false; cShadowDist.Value = 0f; cTexLimit.Value = 0; cAntiAlias.Value = -1; cAnisoOff.Value = false; cLodBias.Value = 0f; cPixelLights.Value = -1; cSimpleSkin.Value = false; cReflProbesOff.Value = false; cCameraFar.Value = 0f; cVsync.Value = -1; cMemGuard.Value = false; cHideWater.Value = false; SavePreset(); } else { bool flag = value == "Potato"; cParticles.Value = true; cDistRenderers.Value = true; cRenderDist.Value = (flag ? 35f : 50f); cDistLights.Value = true; cLightDist.Value = (flag ? 18f : 30f); cDistAudio.Value = true; cAudioDist.Value = (flag ? 30f : 40f); cAnimCull.Value = false; cChunk.Value = (flag ? 80 : 150); cScanInterval.Value = (flag ? 8f : 5f); cPauseAfterScene.Value = (flag ? 2f : 1.5f); cShaderLevel.Value = 1; cVsync.Value = 0; cMemGuard.Value = true; cLowMemMb.Value = (flag ? 1000 : 800); cShadowsOff.Value = flag; cShadowDist.Value = (flag ? 0f : 20f); cTexLimit.Value = (flag ? 1 : 0); cAntiAlias.Value = 0; cAnisoOff.Value = true; cLodBias.Value = 0f; cPixelLights.Value = 2; cSimpleSkin.Value = flag; cReflProbesOff.Value = true; cCameraFar.Value = (flag ? 150f : 0f); SavePreset(); } } } private static void SavePreset() { try { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Config.Save(); } } catch { } } private static void ApplyQuality() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Invalid comparison between Unknown and I4 try { if (cEnabled.Value) { if (cShadowsOff.Value && (int)QualitySettings.shadows != 0) { QualitySettings.shadows = (ShadowQuality)0; } if (cShadowDist.Value > 0f && QualitySettings.shadowDistance > cShadowDist.Value) { QualitySettings.shadowDistance = cShadowDist.Value; } if (cTexLimit.Value > 0 && QualitySettings.globalTextureMipmapLimit != cTexLimit.Value) { QualitySettings.globalTextureMipmapLimit = cTexLimit.Value; } if (cAntiAlias.Value >= 0 && QualitySettings.antiAliasing != cAntiAlias.Value) { QualitySettings.antiAliasing = cAntiAlias.Value; } if (cAnisoOff.Value && (int)QualitySettings.anisotropicFiltering != 0) { QualitySettings.anisotropicFiltering = (AnisotropicFiltering)0; } if (cLodBias.Value > 0f && QualitySettings.lodBias > cLodBias.Value) { QualitySettings.lodBias = cLodBias.Value; } if (cPixelLights.Value >= 0 && QualitySettings.pixelLightCount != cPixelLights.Value) { QualitySettings.pixelLightCount = cPixelLights.Value; } if (cSimpleSkin.Value && (int)QualitySettings.skinWeights != 1) { QualitySettings.skinWeights = (SkinWeights)1; } if (cReflProbesOff.Value && QualitySettings.realtimeReflectionProbes) { QualitySettings.realtimeReflectionProbes = false; } } } catch { } } private static void ApplyFpsSettings() { if (cFpsLimit.Value > 0) { Application.targetFrameRate = cFpsLimit.Value; } if (cVsync.Value >= 0) { QualitySettings.vSyncCount = Mathf.Clamp(cVsync.Value, 0, 1); } } private static void ApplyLod() { if (cGlobalLod.Value > 0) { Shader.globalMaximumLOD = cGlobalLod.Value; } } private void Awake() { Instance = this; BindConfig(); ApplyPresetIfNeeded(); ParseLists(); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { ApplyPresetIfNeeded(); ParseLists(); ApplyFpsSettings(); ApplyLod(); ApplyQuality(); }; renderCuller = new Culler<Renderer>((Renderer r) => !(r is ParticleSystemRenderer) && !Excluded((Component)(object)r) && SeenByMainCamera(r) && !IsTextRenderer(r), (Renderer r) => r.enabled, delegate(Renderer r, bool v) { r.enabled = v; }, delegate(Renderer r, Vector3 c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = r.bounds; return ((Bounds)(ref bounds)).SqrDistance(c); }); lightCuller = new Culler<Light>((Light l) => (int)l.type != 1 && !Excluded((Component)(object)l), (Light l) => ((Behaviour)l).enabled, delegate(Light l, bool v) { ((Behaviour)l).enabled = v; }, delegate(Light l, Vector3 c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)l).transform.position - c; return ((Vector3)(ref val)).sqrMagnitude; }); audioCuller = new Culler<AudioSource>((AudioSource a) => a.spatialBlend > 0.01f && !Excluded((Component)(object)a), (AudioSource a) => !a.mute, delegate(AudioSource a, bool v) { a.mute = !v; }, delegate(AudioSource a, Vector3 c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)a).transform.position - c; return ((Vector3)(ref val)).sqrMagnitude; }); PatchHarmony(); SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; Application.quitting += OnQuitting; ApplyFpsSettings(); ApplyLod(); ApplyQuality(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Game " + Application.version + ", Unity " + Application.unityVersion)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"REPO Optimizer loaded."); } private void PatchHarmony() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown try { Harmony val = new Harmony("REPOOptimizer.Performance"); MethodInfo methodInfo = AccessTools.Method(typeof(ParticleSystem), "Play", new Type[1] { typeof(bool) }, (Type[])null); val.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(ParticlePatch).GetMethod("Prefix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Harmony: ParticleSystem.Play patched."); try { HarmonyMethod val2 = new HarmonyMethod(typeof(SpawnPatch).GetMethod("Postfix")); Type typeFromHandle = typeof(Object); Type[][] obj = new Type[4][] { new Type[1] { typeFromHandle }, new Type[3] { typeFromHandle, typeof(Vector3), typeof(Quaternion) }, new Type[2] { typeFromHandle, typeof(Transform) }, new Type[4] { typeFromHandle, typeof(Vector3), typeof(Quaternion), typeof(Transform) } }; int num = 0; Type[][] array = obj; foreach (Type[] array2 in array) { MethodInfo methodInfo2 = AccessTools.Method(typeFromHandle, "Instantiate", array2, (Type[])null); if (methodInfo2 != null) { val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Harmony: Instantiate overloads patched: " + num)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Harmony Instantiate: " + ex.Message)); } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Harmony particle patch failed, using scanning only: " + ex2.Message)); } } private void OnSceneLoaded(Scene s, LoadSceneMode m) { Crumb("scene event: " + ((Scene)(ref s)).name); renderCuller.RestoreAll(); renderCuller.Reset(); lightCuller.RestoreAll(); lightCuller.Reset(); audioCuller.RestoreAll(); audioCuller.Reset(); pauseUntil = Time.unscaledTime + Mathf.Max(0f, cPauseAfterScene.Value); scanCount = 0; cartValue = -1f; zeroSince.Clear(); killTries.Clear(); ApplyQuality(); killedParticles.Clear(); ClearCaches(); sleepDone.Clear(); animDone.Clear(); mats.Clear(); matSeen.Clear(); originalShaders.Clear(); matIdx = 0; appliedShaderLevel = 0; loggedShadersThisScene = false; cam = null; scanTimer = 0.5f; particleTimer = 0.3f; burstUntil = Time.unscaledTime + 25f; } private void OnSceneUnloaded(Scene s) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) OnSceneLoaded(s, (LoadSceneMode)0); } private void OnQuitting() { try { if (muted) { muted = false; RestoreAudio(); } Crumb("quitting"); if (sw != null) { sw.Close(); } } catch { } } private Camera GetCam() { if ((Object)(object)cam != (Object)null && ((Behaviour)cam).isActiveAndEnabled) { if (!renderOff) { camMask = cam.cullingMask; } return cam; } if (Time.unscaledTime < camRetry) { return null; } camRetry = Time.unscaledTime + 1f; cam = Camera.main; if ((Object)(object)cam == (Object)null) { Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if ((Object)(object)val.targetTexture == (Object)null) { cam = val; break; } } } if ((Object)(object)cam != (Object)null && !renderOff) { camMask = cam.cullingMask; } return cam; } private void Crumb(string m) { if (!cDebugLog.Value) { return; } try { if (sw == null) { sw = new StreamWriter(new FileStream(Path.Combine(OutDir(), "session.log"), FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { AutoFlush = true }; } if (++crumbLines > 4000) { crumbLines = 0; sw.Close(); sw = new StreamWriter(new FileStream(Path.Combine(OutDir(), "session.log"), FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { AutoFlush = true }; sw.WriteLine("--- rotated ---"); } sw.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " " + m); } catch { } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[dbg] " + m)); } private void Safe(string name, Action a) { try { Crumb(name); a(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(name + ": " + ex.Message)); } } private void Update() { try { UpdateInner(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Update: " + ex.Message)); } } private void UpdateInner() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_04b3: Unknown result type (might be due to invalid IL or missing references) frameMs = Mathf.Lerp(frameMs, Time.unscaledDeltaTime * 1000f, 0.05f); if (!hotkeyBroken) { try { if (Input.GetKeyDown(cFpsKey.Value)) { cShowFps.Value = !cShowFps.Value; } if (Input.GetKeyDown(cDumpKey.Value)) { DumpClasses(); } if (Input.GetKeyDown(cInspectKey.Value)) { InspectTarget(); } if (Input.GetKeyDown(cRenderKey.Value) && (!cRenderCtrl.Value || Input.GetKey((KeyCode)306))) { ToggleRenderOff(); } if (Input.GetKeyDown(cMuteKey.Value) && (!cMuteCtrl.Value || Input.GetKey((KeyCode)306))) { ToggleMute(); } } catch { hotkeyBroken = true; } } if (renderOff) { renderOffTimer -= Time.unscaledDeltaTime; if (renderOffTimer <= 0f) { renderOffTimer = 0.5f; ApplyRenderOff(); } } if (muted) { muteTimer -= Time.unscaledDeltaTime; if (muteTimer <= 0f) { muteTimer = 1f; ApplyMute(); } } memTimer -= Time.unscaledDeltaTime; if (memTimer <= 0f) { memTimer = 1f; try { CheckMemory(); } catch { } ApplyQuality(); } if (!cEnabled.Value) { renderCuller.RestoreAll(); lightCuller.RestoreAll(); audioCuller.RestoreAll(); RestoreShaders(); } else { if (Time.unscaledTime < pauseUntil) { return; } enemyTimer -= Time.unscaledDeltaTime; if (enemyTimer <= 0f) { enemyTimer = 1f; if (cEnemyFix.Value) { try { CheckZeroHpEnemies(); } catch (Exception ex) { if (!enemyErrLogged) { enemyErrLogged = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("EnemyFix: " + ex.Message)); } } } } cartTimer -= Time.unscaledDeltaTime; if (cartTimer <= 0f) { cartTimer = 2f; if (cCartHud.Value) { try { UpdateCartValue(); } catch (Exception ex2) { if (!cartErrLogged) { cartErrLogged = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("CartValue: " + ex2.Message)); } cartValue = -1f; } } } if (!cDistRenderers.Value) { renderCuller.RestoreAll(); } if (!cDistLights.Value) { lightCuller.RestoreAll(); } if (!cDistAudio.Value) { audioCuller.RestoreAll(); } particleTimer -= Time.unscaledDeltaTime; if (particleTimer <= 0f) { particleTimer = ((Time.unscaledTime < burstUntil) ? 0.5f : Mathf.Max(0.2f, cParticleScanInterval.Value)); if (cParticles.Value || cWaterParticles.Value || WaterHideActive || (pressure && cMemGuard.Value)) { ScanParticles(); } } scanTimer -= Time.unscaledDeltaTime; if (scanTimer <= 0f) { scanTimer = ((Time.unscaledTime < burstUntil) ? 1.5f : Mathf.Max(1f, cScanInterval.Value)); Scan(); } Camera val = GetCam(); if ((Object)(object)val != (Object)null) { if (cCameraFar.Value > 0f && val.farClipPlane > cCameraFar.Value) { val.farClipPlane = cCameraFar.Value; } Vector3 position = ((Component)val).transform.position; int num = Mathf.Max(10, cChunk.Value); if (Time.unscaledTime < burstUntil) { num *= 4; } if (cDistRenderers.Value) { renderCuller.Step(position, cRenderDist.Value * DistMul, num); } if (cDistLights.Value) { lightCuller.Step(position, cLightDist.Value * DistMul, num); } if (cDistAudio.Value) { audioCuller.Step(position, cAudioDist.Value * DistMul, num); } } ShaderStep(); } } private void Scan() { Crumb("scan start"); Renderer[] renderers = null; Safe("find renderers", delegate { renderers = Object.FindObjectsByType<Renderer>((FindObjectsSortMode)0); }); if (renderers == null) { renderers = (Renderer[])(object)new Renderer[0]; } scanCount++; if (cDistRenderers.Value) { Safe("rescan renderers", delegate { renderCuller.Rescan(renderers); }); } if (cDistLights.Value) { Safe("rescan lights", delegate { lightCuller.Rescan(Object.FindObjectsByType<Light>((FindObjectsSortMode)0)); }); } if (cDistAudio.Value) { Safe("rescan audio", delegate { audioCuller.Rescan(Object.FindObjectsByType<AudioSource>((FindObjectsSortMode)0)); }); } if (cAnimCull.Value) { Safe("animators", delegate { Animator[] array = Object.FindObjectsByType<Animator>((FindObjectsSortMode)0); foreach (Animator val in array) { if (!((Object)(object)val == (Object)null) && !animDone.Contains(val)) { val.cullingMode = (AnimatorCullingMode)1; animDone.Add(val); } } }); } if (cPhysics.Value) { Safe("physics", delegate { sleepDone.RemoveWhere((Rigidbody r) => (Object)(object)r == (Object)null); Rigidbody[] array = Object.FindObjectsByType<Rigidbody>((FindObjectsSortMode)0); foreach (Rigidbody val in array) { if (!((Object)(object)val == (Object)null) && !sleepDone.Contains(val)) { val.sleepThreshold = cSleepThreshold.Value; sleepDone.Add(val); } } }); } Safe("water", delegate { ApplyWater(renderers); }); if (cShaderLevel.Value >= 1 && (scanCount <= 3 || scanCount % 6 == 0)) { Safe("postprocess", DisablePostProcessing); } if (cShaderLevel.Value >= 2 || cLogShaders.Value) { Safe("materials", delegate { CollectMaterials(renderers); }); } if (cLogShaders.Value && !loggedShadersThisScene) { Safe("log shaders", LogShaders); } Safe("quality", ApplyQuality); Crumb("scan end"); } private void ScanParticles() { ParticleSystem[] array = Object.FindObjectsByType<ParticleSystem>((FindObjectsSortMode)0); foreach (ParticleSystem val in array) { if (!((Object)(object)val == (Object)null) && !killedParticles.Contains(val) && ((pressure && cMemGuard.Value) || (WaterHideActive && IsWaterObject((Component)(object)val)) || (cWaterParticles.Value && IsWaterParticle(val)) || (cParticles.Value && !NameHas((Component)(object)val, exParticles)))) { KillParticle(val); killedParticles.Add(val); } } } internal static void KillParticle(ParticleSystem ps) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) try { ps.Stop(true, (ParticleSystemStopBehavior)0); MainModule main = ps.main; ((MainModule)(ref main)).maxParticles = 0; EmissionModule emission = ps.emission; ((EmissionModule)(ref emission)).enabled = false; ParticleSystemRenderer component = ((Component)ps).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = false; } } catch { } } internal static bool ShouldBlockParticle(ParticleSystem ps) { try { if (!cEnabled.Value || (Object)(object)ps == (Object)null) { return false; } if (pressure && cMemGuard.Value) { return true; } if (cWaterParticles.Value && IsWaterParticle(ps)) { return true; } if (WaterHideActive && IsWaterObject((Component)(object)ps)) { return true; } if (!cParticles.Value) { return false; } if (exParticles.Count == 0) { return true; } int instanceID = ((Object)ps).GetInstanceID(); if (!particleExCache.TryGetValue(instanceID, out var value)) { value = NameHas((Component)(object)ps, exParticles); particleExCache[instanceID] = value; } return !value; } catch { return false; } } private void ApplyWater(Renderer[] rs) { if (WaterHideActive) { foreach (Renderer val in rs) { if (!((Object)(object)val == (Object)null) && val.enabled && !(val is ParticleSystemRenderer) && IsWaterRenderer(val)) { val.enabled = false; waterHidden.Add(val); } } } else { if (waterHidden.Count <= 0) { return; } foreach (Renderer item in waterHidden) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } waterHidden.Clear(); } } internal static void OnSpawned(Object result) { try { bool flag = pressure && cMemGuard.Value; if (!flag && (!cSpawnLog.Value || !cDebugLog.Value)) { return; } GameObject val = (GameObject)(object)((result is GameObject) ? result : null); if ((Object)(object)val == (Object)null) { return; } string name = ((Object)val).name; if (cSpawnLog.Value && cDebugLog.Value && (Object)(object)Instance != (Object)null) { float unscaledTime = Time.unscaledTime; if (unscaledTime - spawnWin > 1f) { spawnWin = unscaledTime; spawnCnt = 0; } if (++spawnCnt <= 25) { Instance.Crumb("spawn: " + name + (flag ? " [lowmem]" : "")); } } if (!flag || (!ListHas(name, tempKw) && (!WaterHideActive || !ListHas(name, waterKw)))) { return; } Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } } catch { } } private void DisablePostProcessing() { if (postTypes.Count == 0) { return; } Behaviour[] array = Object.FindObjectsByType<Behaviour>((FindObjectsSortMode)0); foreach (Behaviour val in array) { if (!((Object)(object)val == (Object)null) && val.enabled) { string item = ((object)val).GetType().Name.ToLowerInvariant(); if (postTypes.Contains(item)) { val.enabled = false; } } } } private void CollectMaterials(Renderer[] renderers) { foreach (Renderer val in renderers) { if ((Object)(object)val == (Object)null || val is ParticleSystemRenderer || Excluded((Component)(object)val)) { continue; } Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if (!((Object)(object)val2 == (Object)null) && !matSeen.Contains(val2)) { matSeen.Add(val2); mats.Add(val2); } } } } private void LogShaders() { loggedShadersThisScene = true; Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (Material mat in mats) { if (!((Object)(object)mat == (Object)null) && !((Object)(object)mat.shader == (Object)null)) { string name = ((Object)mat.shader).name; dictionary[name] = ((!dictionary.ContainsKey(name)) ? 1 : (dictionary[name] + 1)); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"=== Shaders in scene (name : materials) ==="); foreach (KeyValuePair<string, int> item in dictionary.OrderByDescending((KeyValuePair<string, int> k) => k.Value)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(item.Key + " : " + item.Value)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"==========================================="); } private Shader FindShader(params string[] names) { foreach (string text in names) { if (!shaderCache.TryGetValue(text, out var value)) { value = Shader.Find(text); shaderCache[text] = value; } if ((Object)(object)value != (Object)null) { return value; } } return null; } private void RestoreShaders() { if (originalShaders.Count == 0) { appliedShaderLevel = 0; return; } foreach (KeyValuePair<Material, Shader> originalShader in originalShaders) { if ((Object)(object)originalShader.Key != (Object)null && (Object)(object)originalShader.Value != (Object)null) { originalShader.Key.shader = originalShader.Value; } } originalShaders.Clear(); matIdx = 0; appliedShaderLevel = 0; } private void ShaderStep() { //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: 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) int value = cShaderLevel.Value; if (value < 2) { RestoreShaders(); return; } if (appliedShaderLevel != value) { RestoreShaders(); appliedShaderLevel = value; } if (mats.Count == 0) { return; } Shader val = ((value >= 3) ? FindShader("Unlit/Texture", "Mobile/Unlit (Supports Lightmap)") : FindShader("Legacy Shaders/Diffuse", "Mobile/Diffuse")); if ((Object)(object)val == (Object)null) { if (!warnedNoShader) { warnedNoShader = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"No suitable simple shader found in the game build - shader replacement is not possible."); } return; } int num = Mathf.Max(10, cChunk.Value / 3); for (int i = 0; i < num; i++) { if (mats.Count <= 0) { break; } if (matIdx >= mats.Count) { matIdx = 0; } Material val2 = mats[matIdx++]; if ((Object)(object)val2 == (Object)null || originalShaders.ContainsKey(val2) || (Object)(object)val2.shader == (Object)null || (Object)(object)val2.shader == (Object)(object)val) { continue; } string text = ((Object)val2.shader).name.ToLowerInvariant(); bool flag = false; foreach (string exShader in exShaders) { if (text.Contains(exShader)) { flag = true; break; } } if (flag) { continue; } try { Texture val3 = null; Color val4 = Color.white; bool flag2 = false; if (val2.HasProperty("_MainTex")) { val3 = val2.GetTexture("_MainTex"); } if ((Object)(object)val3 == (Object)null && val2.HasProperty("_BaseMap")) { val3 = val2.GetTexture("_BaseMap"); } if (val2.HasProperty("_Color")) { val4 = val2.GetColor("_Color"); flag2 = true; } else if (val2.HasProperty("_BaseColor")) { val4 = val2.GetColor("_BaseColor"); flag2 = true; } originalShaders[val2] = val2.shader; val2.shader = val; if ((Object)(object)val3 != (Object)null && val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", val3); } if (flag2 && val2.HasProperty("_Color")) { val2.SetColor("_Color", val4); } } catch { } } } [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool GlobalMemoryStatusEx([In][Out] MemStatus lpBuffer); private void CheckMemory() { if (!cMemGuard.Value) { pressure = false; return; } MemStatus memStatus = new MemStatus(); if (!GlobalMemoryStatusEx(memStatus)) { return; } double num = (double)Math.Min(memStatus.ullAvailPhys, memStatus.ullAvailPageFile) / 1048576.0; bool flag = pressure; if (!pressure && num < (double)cLowMemMb.Value) { pressure = true; } else if (pressure && num > (double)(cLowMemMb.Value + 300)) { pressure = false; } if (pressure != flag) { string text = (pressure ? "LOW MEMORY: lite mode ON" : "memory OK: lite mode off") + " (free " + num.ToString("0") + " MB)"; ((BaseUnityPlugin)this).Logger.LogWarning((object)text); Crumb(text); if (pressure && cMemCleanup.Value && Time.unscaledTime - lastCleanup > 90f) { lastCleanup = Time.unscaledTime; ((MonoBehaviour)this).StartCoroutine(CleanupRoutine()); } } } private IEnumerator CleanupRoutine() { Crumb("cleanup: UnloadUnusedAssets"); yield return Resources.UnloadUnusedAssets(); GC.Collect(); Crumb("cleanup done"); } private void FindCartTypes() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!assembly.GetName().Name.StartsWith("Assembly-CSharp")) { continue; } Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } Type[] array2 = array; foreach (Type type in array2) { if (cartType == null && type.Name == "PhysGrabCart") { cartType = type; } if (valuableType == null && type.Name == "ValuableObject") { valuableType = type; } } } if (cartType != null) { string[] cartFieldNames = CartFieldNames; foreach (string name in cartFieldNames) { FieldInfo fieldInfo = FindField(cartType, name); if (fieldInfo != null && IsNumeric(fieldInfo.FieldType)) { cartDirectField = fieldInfo; break; } } } if (valuableType != null) { string[] cartFieldNames = ValuableFieldNames; foreach (string name2 in cartFieldNames) { FieldInfo fieldInfo2 = FindField(valuableType, name2); if (fieldInfo2 != null && IsNumeric(fieldInfo2.FieldType)) { valuableValueField = fieldInfo2; break; } } } string text = "Cart HUD: cart=" + ((cartType != null) ? cartType.Name : "NOT FOUND") + ", direct field=" + ((cartDirectField != null) ? cartDirectField.Name : "none") + ", valuable=" + ((valuableType != null) ? valuableType.Name : "NOT FOUND") + ", value field=" + ((valuableValueField != null) ? valuableValueField.Name : "none"); ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } private void UpdateCartValue() { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: 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_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) if (!cartTypesSearched) { cartTypesSearched = true; FindCartTypes(); } if (cartType == null) { cartValue = -1f; return; } Object[] array = Object.FindObjectsByType(cartType, (FindObjectsSortMode)0); if (array.Length == 0) { cartValue = -1f; return; } Object[] array2; if (cartDirectField != null) { double num = 0.0; array2 = array; foreach (Object val in array2) { if (!(val == (Object)null)) { num += ToDouble(cartDirectField.GetValue(val)); } } cartValue = (float)num; return; } if (valuableType == null || valuableValueField == null) { cartValue = -1f; return; } List<Bounds> list = new List<Bounds>(); array2 = array; foreach (Object obj in array2) { Component val2 = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)val2 == (Object)null) { continue; } bool flag = false; Bounds item = default(Bounds); Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(false); foreach (Collider val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && val3.enabled) { if (!flag) { item = val3.bounds; flag = true; } else { ((Bounds)(ref item)).Encapsulate(val3.bounds); } } } if (flag) { ((Bounds)(ref item)).Expand(0.2f); list.Add(item); } } double num2 = 0.0; if (list.Count > 0) { array2 = Object.FindObjectsByType(valuableType, (FindObjectsSortMode)0); foreach (Object obj2 in array2) { Component val4 = (Component)(object)((obj2 is Component) ? obj2 : null); if ((Object)(object)val4 == (Object)null) { continue; } Vector3 position = val4.transform.position; foreach (Bounds item2 in list) { Bounds current = item2; if (((Bounds)(ref current)).Contains(position)) { num2 += ToDouble(valuableValueField.GetValue(val4)); break; } } } } cartValue = (float)num2; } private bool IsHost() { if (!photonSearched) { photonSearched = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = null; try { type = assembly.GetType("Photon.Pun.PhotonNetwork", throwOnError: false); } catch { } if (!(type == null)) { masterProp = type.GetProperty("IsMasterClient", BindingFlags.Static | BindingFlags.Public); break; } } } if (masterProp == null) { return false; } try { return (bool)masterProp.GetValue(null, null); } catch { return false; } } private void FindEnemyTypes() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!assembly.GetName().Name.StartsWith("Assembly-CSharp")) { continue; } Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } Type[] array2 = array; foreach (Type type in array2) { if (type.Name == "EnemyHealth") { healthType = type; break; } } if (healthType != null) { break; } } if (healthType != null) { string[] hpFieldNames = HpFieldNames; foreach (string name in hpFieldNames) { FieldInfo fieldInfo = FindField(healthType, name); if (fieldInfo != null && IsNumeric(fieldInfo.FieldType)) { hpField = fieldInfo; break; } } hpFieldNames = DeadFieldNames; foreach (string name2 in hpFieldNames) { FieldInfo fieldInfo2 = FindField(healthType, name2); if (fieldInfo2 != null && fieldInfo2.FieldType == typeof(bool)) { deadField = fieldInfo2; break; } } hpFieldNames = KillMethodNames; foreach (string n in hpFieldNames) { MethodInfo[] array3 = (from m in healthType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == n orderby m.GetParameters().Length select m).ToArray(); if (array3.Length != 0) { killMethod = array3[0]; break; } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("EnemyFix: class=" + ((healthType != null) ? healthType.Name : "NOT FOUND") + ", hp=" + ((hpField != null) ? hpField.Name : "none") + ", dead flag=" + ((deadField != null) ? deadField.Name : "none") + ", kill method=" + ((killMethod != null) ? killMethod.Name : "none"))); } private void CheckZeroHpEnemies() { //IL_01a8: Unknown result type (might be due to invalid IL or missing references) if (!IsHost()) { return; } if (!enemyTypesSearched) { enemyTypesSearched = true; FindEnemyTypes(); } if (healthType == null || hpField == null || deadField == null || killMethod == null) { if (!enemyNotReadyLogged) { enemyNotReadyLogged = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"EnemyFix inactive: the game's enemy health members were not found (the game may have changed)."); } return; } float unscaledTime = Time.unscaledTime; Object[] array = Object.FindObjectsByType(healthType, (FindObjectsSortMode)0); foreach (Object obj in array) { Component val = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)val == (Object)null) { continue; } int instanceID = ((Object)val).GetInstanceID(); bool flag = false; try { flag = (bool)deadField.GetValue(val); } catch { } double num = ToDouble(hpField.GetValue(val)); float value; if (flag || num > 0.0) { zeroSince.Remove(instanceID); } else if (!zeroSince.TryGetValue(instanceID, out value)) { zeroSince[instanceID] = unscaledTime; } else { if (unscaledTime - value < 3f) { continue; } killTries.TryGetValue(instanceID, out var value2); if (value2 >= 3) { continue; } killTries[instanceID] = value2 + 1; zeroSince[instanceID] = unscaledTime; ParameterInfo[] parameters = killMethod.GetParameters(); object[] array2 = new object[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { Type parameterType = parameters[j].ParameterType; if (parameterType == typeof(Vector3)) { array2[j] = Vector3.zero; } else if (parameterType.IsValueType) { array2[j] = Activator.CreateInstance(parameterType); } else { array2[j] = null; } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("EnemyFix: finishing '" + ((Object)val.transform.root).name + "' (HP=" + num + ", attempt " + (value2 + 1) + ")")); killMethod.Invoke(val, array2); } } } private void ToggleRenderOff() { try { renderOff = !renderOff; if (renderOff) { ApplyRenderOff(); } else { RestoreRender(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Rendering " + (renderOff ? "OFF" : "on"))); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("ToggleRenderOff: " + ex.Message)); } } private void ApplyRenderOff() { Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if (!((Object)(object)val == (Object)null)) { if (!camMasks.ContainsKey(val)) { camMasks[val] = val.cullingMask; } val.cullingMask = 0; } } } private void RestoreRender() { foreach (KeyValuePair<Camera, int> camMask in camMasks) { if ((Object)(object)camMask.Key != (Object)null) { camMask.Key.cullingMask = camMask.Value; } } camMasks.Clear(); } private void ToggleMute() { try { muted = !muted; if (muted) { if (AudioListener.volume > 0.001f) { savedVolume = AudioListener.volume; } muteTimer = 0f; ApplyMute(); } else { RestoreAudio(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Mute " + (muted ? "ON" : "off") + " (" + cMuteTarget.Value + ")")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("ToggleMute: " + ex.Message)); } } private void ApplyMute() { if (cMuteTarget.Value == "VoicesOnly") { AudioSource[] array = Object.FindObjectsByType<AudioSource>((FindObjectsSortMode)0); foreach (AudioSource val in array) { if (!((Object)(object)val == (Object)null) && !val.mute && !mutedSources.Contains(val) && IsVoiceSource(val)) { val.mute = true; mutedSources.Add(val); } } } else if (AudioListener.volume != 0f) { AudioListener.volume = 0f; } } private void RestoreAudio() { AudioListener.volume = savedVolume; foreach (AudioSource mutedSource in mutedSources) { if ((Object)(object)mutedSource != (Object)null) { mutedSource.mute = false; } } mutedSources.Clear(); } private void OnGUI() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown float num = 34f; if (renderOff) { GUI.Label(new Rect(10f, num, 600f, 24f), "Rendering is OFF - press " + ((object)cRenderKey.Value/*cast due to .constrained prefix*/).ToString() + " to restore"); num += 22f; } if (muted) { GUI.Label(new Rect(10f, num, 600f, 24f), "Muted - press " + ((object)cMuteKey.Value/*cast due to .constrained prefix*/).ToString() + " to unmute"); } if (cShowFps.Value) { float num2 = 1000f / Mathf.Max(0.1f, frameMs); GUI.Label(new Rect(10f, 10f, 300f, 24f), $"FPS {num2:0} ({frameMs:0.0} ms)"); } if (cCartHud.Value && cartValue >= 0f) { float num3 = (float)Screen.height / 768f; if (hudStyle == null) { hudStyle = new GUIStyle(GUI.skin.label); hudStyle.alignment = (TextAnchor)2; hudStyle.fontStyle = (FontStyle)1; } hudStyle.fontSize = Mathf.Max(12, Mathf.RoundToInt(22f * num3)); string text = cHudLabel.Value + " $" + FormatMoney(cartValue); Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width - 582f * num3, cHudOffsetY.Value * num3, 560f * num3, 40f * num3); hudStyle.normal.textColor = Color.black; GUI.Label(new Rect(((Rect)(ref val)).x + 2f, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), text, hudStyle); hudStyle.normal.textColor = new Color(1f, 0.85f, 0.3f); GUI.Label(val, text, hudStyle); } } private void InspectTarget() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_0595: Unknown result type (might be due to invalid IL or missing references) //IL_059a: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Unknown result type (might be due to invalid IL or missing references) //IL_05dc: Unknown result type (might be due to invalid IL or missing references) try { Camera val = GetCam(); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Inspect: no camera found"); return; } RaycastHit[] array = Physics.RaycastAll(((Component)val).transform.position, ((Component)val).transform.forward, 8f, -1, (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== Inspect " + DateTime.Now.ToString("s") + " ==="); stringBuilder.AppendLine("Quality: pixelLights=" + QualitySettings.pixelLightCount + " shadows=" + ((object)QualitySettings.shadows/*cast due to .constrained prefix*/).ToString() + " texLimit=" + QualitySettings.globalTextureMipmapLimit + " lodBias=" + QualitySettings.lodBias + " globalLOD=" + Shader.globalMaximumLOD); if (array.Length == 0) { stringBuilder.AppendLine("The ray hit nothing. Aim at an object closer than 8 m."); } else { RaycastHit val2 = array[0]; RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val3 = array2[num]; if (!((Object)((Component)((RaycastHit)(ref val3)).collider).transform.root).name.ToLowerInvariant().Contains("player")) { val2 = val3; break; } } Transform root = ((Component)((RaycastHit)(ref val2)).collider).transform.root; Vector3 pt = ((RaycastHit)(ref val2)).point; stringBuilder.AppendLine("HIT '" + ((Object)((RaycastHit)(ref val2)).collider).name + "' root '" + ((Object)root).name + "' layer " + LayerMask.LayerToName(((Component)((RaycastHit)(ref val2)).collider).gameObject.layer) + " dist " + ((RaycastHit)(ref val2)).distance.ToString("0.0")); foreach (Renderer item in (from r in ((Component)root).GetComponentsInChildren<Renderer>(true) where (Object)(object)r != (Object)null select r).OrderBy(delegate(Renderer r) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = r.bounds; return ((Bounds)(ref bounds)).SqrDistance(pt); }).Take(40)) { List<string> list = new List<string>(); Material[] sharedMaterials = item.sharedMaterials; foreach (Material val4 in sharedMaterials) { if ((Object)(object)val4 != (Object)null && (Object)(object)val4.shader != (Object)null) { list.Add(((Object)val4.shader).name); } } stringBuilder.AppendLine(" R " + ((object)item).GetType().Name + " '" + ((Object)item).name + "' enabled=" + item.enabled + " active=" + ((Component)item).gameObject.activeInHierarchy + " layer=" + LayerMask.LayerToName(((Component)item).gameObject.layer) + " hiddenByMod=" + renderCuller.IsHidden(item) + " excluded=" + Excluded((Component)(object)item) + " isText=" + IsTextRenderer(item) + " shaders=[" + string.Join("; ", list.ToArray()) + "]"); } Component[] componentsInChildren = ((Component)root).GetComponentsInChildren<Component>(true); Vector3 val6; foreach (Component val5 in componentsInChildren) { if ((Object)(object)val5 == (Object)null) { continue; } string name = ((object)val5).GetType().Name; if (name.IndexOf("TextMeshPro", StringComparison.OrdinalIgnoreCase) < 0) { continue; } val6 = val5.transform.position - pt; if (((Vector3)(ref val6)).sqrMagnitude > 64f) { continue; } string text = ""; try { PropertyInfo property = ((object)val5).GetType().GetProperty("text"); if (property != null) { text = Convert.ToString(property.GetValue(val5, null)); } } catch { } Behaviour val7 = (Behaviour)(object)((val5 is Behaviour) ? val5 : null); stringBuilder.AppendLine(" TEXT " + name + " '" + ((Object)val5).name + "' enabled=" + (((Object)(object)val7 != (Object)null) ? val7.enabled.ToString() : "?") + " text='" + text + "'"); } Light[] array3 = Object.FindObjectsByType<Light>((FindObjectsSortMode)0); foreach (Light val8 in array3) { if (!((Object)(object)val8 == (Object)null)) { val6 = ((Component)val8).transform.position - pt; float magnitude = ((Vector3)(ref val6)).magnitude; if (!(magnitude > 12f)) { stringBuilder.AppendLine(" LIGHT '" + ((Object)val8).name + "' type=" + ((object)val8.type/*cast due to .constrained prefix*/).ToString() + " enabled=" + ((Behaviour)val8).enabled + " active=" + ((Component)val8).gameObject.activeInHierarchy + " hiddenByMod=" + lightCuller.IsHidden(val8) + " range=" + val8.range.ToString("0.0") + " intensity=" + val8.intensity.ToString("0.0") + " dist=" + magnitude.ToString("0.0")); } } } } string text2 = Path.Combine(OutDir(), "inspect.txt"); File.AppendAllText(text2, stringBuilder.ToString() + "\n"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Inspect written: " + text2)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("InspectTarget: " + ex.Message)); } } private void DumpClasses() { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== Dump " + DateTime.Now.ToString("s") + " ==="); stringBuilder.AppendLine("Unity layers:"); for (int i = 0; i < 32; i++) { string text = LayerMask.LayerToName(i); if (!string.IsNullOrEmpty(text)) { stringBuilder.AppendLine(" " + i + " = " + text); } } stringBuilder.AppendLine("Main camera mask: " + camMask); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { string name = assembly.GetName().Name; if (!name.StartsWith("Assembly-CSharp")) { continue; } Type[] array; try { array = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); } stringBuilder.AppendLine("Assembly " + name + ", types: " + array.Length); Type[] array2 = array; foreach (Type type in array2) { string text2 = type.Name.ToLowerInvariant(); if (!text2.Contains("mouth") && !text2.Contains("voice") && !text2.Contains("speak") && !text2.Contains("cart") && !text2.Contains("enemy") && !text2.Contains("valuable") && !text2.Contains("orb") && !text2.Contains("health") && !text2.Contains("stun") && !text2.Contains("death")) { continue; } stringBuilder.AppendLine("TYPE " + type.FullName + " : " + ((type.BaseType != null) ? type.BaseType.Name : "")); if (!text2.Contains("mouth") && !text2.Contains("voice") && !text2.Contains("cart") && !text2.Contains("health") && !text2.Contains("stun") && !text2.Contains("valuable") && !text2.Contains("death") && !(text2 == "enemy") && !(text2 == "enemyparent")) { continue; } FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { stringBuilder.AppendLine(" field " + fieldInfo.FieldType.Name + " " + fieldInfo.Name); } MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { stringBuilder.AppendLine(" method " + methodInfo.ReturnType.Name + " " + methodInfo.Name + "(" + string.Join(", ", (from x in methodInfo.GetParameters() select x.ParameterType.Name + " " + x.Name).ToArray()) + ")"); } } } string text3 = Path.Combine(OutDir(), "dump.txt"); File.WriteAllText(text3, stringBuilder.ToString()); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Dump written: " + text3)); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("DumpClasses: " + ex2.Message)); } } } internal static class ParticlePatch { public static bool Prefix(ParticleSystem __instance) { if (Plugin.ShouldBlockParticle(__instance)) { return false; } return true; } } internal static class SpawnPatch { public static void Postfix(Object __result) { Plugin.OnSpawned(__result); } } internal class Culler<T> where T : Component { private readonly List<T> list = new List<T>(); private readonly HashSet<T> hidden = new HashSet<T>(); private readonly Func<T, bool> include; private readonly Func<T, bool> isOn; private readonly Action<T, bool> setOn; private readonly Func<T, Vector3, float> sqrDist; private int idx; public Culler(Func<T, bool> include, Func<T, bool> isOn, Action<T, bool> setOn, Func<T, Vector3, float> sqrDist) { this.include = include; this.isOn = isOn; this.setOn = setOn; this.sqrDist = sqrDist; } public void Rescan(IEnumerable<T> source) { list.Clear(); foreach (T item in source) { if ((Object)(object)item != (Object)null && include(item)) { list.Add(item); } } hidden.RemoveWhere((T h) => (Object)(object)h == (Object)null); } public void Step(Vector3 cam, float max, int budget) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) int count = list.Count; if (count == 0) { return; } float num = max * max; float num2 = max * 0.9f * (max * 0.9f); for (int i = 0; i < budget && i < count; i++) { if (idx >= count) { idx = 0; } T val = list[idx++]; if ((Object)(object)val == (Object)null) { continue; } float num3 = sqrDist(val, cam); if (hidden.Contains(val)) { if (num3 < num2) { setOn(val, arg2: true); hidden.Remove(val); } } else if (isOn(val) && num3 > num) { setOn(val, arg2: false); hidden.Add(val); } } } public bool IsHidden(T o) { return hidden.Contains(o); } public void RestoreAll() { if (hidden.Count == 0) { return; } foreach (T item in hidden) { if ((Object)(object)item != (Object)null) { setOn(item, arg2: true); } } hidden.Clear(); } public void Reset() { list.Clear(); hidden.Clear(); idx = 0; } } }