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 VR Shader Fix v0.0.1
plugins/VRShaderFix.dll
Decompiled 5 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using VRShaderFix; using VRShaderFix.utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("VRShaderFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Replaces All Materials to use VR Compatiable Shader Version")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("VRShaderFix")] [assembly: AssemblyTitle("VRShaderFix")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.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; } } } public class ShaderFix : MonoBehaviour { [CompilerGenerated] private sealed class <DelayedShaderFix>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ShaderFix <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedShaderFix>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int num = <>1__state; ShaderFix shaderFix = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; Plugin.Logger.LogDebug((object)"Fixing Shaders"); shaderFix.ReplaceMaterialsFor<Renderer>((IEnumerable<Renderer>)Resources.FindObjectsOfTypeAll<Renderer>()); shaderFix.ReplaceMaterialsFor<SkinnedMeshRenderer>((IEnumerable<SkinnedMeshRenderer>)VRFixUtils.FindAllInLoadedScenes<SkinnedMeshRenderer>(Array.Empty<string>())); shaderFix.ReplaceMaterialsFor<ParticleSystemRenderer>((IEnumerable<ParticleSystemRenderer>)VRFixUtils.FindAllInLoadedScenes<ParticleSystemRenderer>(Array.Empty<string>())); shaderFix.ReplaceTerrainMaterials(Resources.FindObjectsOfTypeAll<Terrain>()); shaderFix.LogMissingShaders(); 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(); } } private static readonly Dictionary<string, Shader> BaseGameHDRPShaders = new Dictionary<string, Shader>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Shader> MissingShaders = new Dictionary<string, Shader>(StringComparer.OrdinalIgnoreCase); public Dictionary<string, Shader> CustomShaders = new Dictionary<string, Shader>(StringComparer.OrdinalIgnoreCase); public HashSet<string> CachedBlacklist { get; set; } public void StartShaderFix() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (Plugin.VRConfig.enableBlacklist.Value) { for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (CachedBlacklist.Contains(((Scene)(ref sceneAt)).name)) { Plugin.Logger.LogWarning((object)("Skipped Applying VR Shader Fix to scene '" + ((Scene)(ref sceneAt)).name + "' because is blacklisted in Config")); return; } } } ((MonoBehaviour)this).StartCoroutine(DelayedShaderFix()); } [IteratorStateMachine(typeof(<DelayedShaderFix>d__8))] private IEnumerator DelayedShaderFix() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedShaderFix>d__8(0) { <>4__this = this }; } private void ReplaceTerrainMaterials(IEnumerable<Terrain> terrains) { Dictionary<Material, Material> dictionary = new Dictionary<Material, Material>(); foreach (Terrain terrain in terrains) { Material materialTemplate = terrain.materialTemplate; if (!IsValidOriginal(materialTemplate)) { continue; } Shader val = ResolveShader(((Object)materialTemplate.shader).name); if ((Object)(object)val == (Object)null) { continue; } if (!dictionary.TryGetValue(materialTemplate, out var value)) { value = CreateVRMaterial(materialTemplate, val); TerrainData terrainData = terrain.terrainData; TerrainLayer[] terrainLayers = terrainData.terrainLayers; value.shaderKeywords = materialTemplate.shaderKeywords; value.renderQueue = materialTemplate.renderQueue; value.SetInt("_LayerCount", terrainLayers.Length); for (int i = 0; i < terrainData.alphamapTextures.Length; i++) { value.SetTexture($"_Control{i}", (Texture)(object)terrainData.alphamapTextures[i]); } for (int j = 0; j < terrainLayers.Length; j++) { TerrainLayer val2 = terrainLayers[j]; value.SetTexture($"_Splat{j}", (Texture)(object)val2.diffuseTexture); value.SetTexture($"_Normal{j}", (Texture)(object)val2.normalMapTexture); value.SetTexture($"_Mask{j}", (Texture)(object)val2.maskMapTexture); } dictionary[materialTemplate] = value; } terrain.materialTemplate = dictionary[materialTemplate]; terrain.terrainData.terrainLayers = terrain.terrainData.terrainLayers; ForceDetailRefresh(terrain); terrain.terrainData.RefreshPrototypes(); terrain.Flush(); } } private Shader ResolveShader(string shaderName) { if (CustomShaders.TryGetValue(shaderName, out var value)) { return value; } if (BaseGameHDRPShaders.TryGetValue(shaderName, out var value2)) { return value2; } if (!MissingShaders.ContainsKey(shaderName)) { MissingShaders.Add(shaderName, Shader.Find(shaderName)); } return VRFixUtils.FindClosestShader(shaderName, CustomShaders) ?? VRFixUtils.FindClosestShader(shaderName, BaseGameHDRPShaders); } private Material CreateVRMaterial(Material original, Shader shader) { //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_001d: Expected O, but got Unknown Material val = new Material(shader) { name = ((Object)original).name + "_VR" }; MaterialUtils.CopyMaterialProperties(original, val); return val; } private bool IsValidOriginal(Material mat) { if ((Object)(object)mat == (Object)null) { return false; } string name = ((Object)mat).name; int num = name.IndexOf(" (", StringComparison.Ordinal); return !((num >= 0) ? name.Substring(0, num) : name).Contains("_VR", StringComparison.OrdinalIgnoreCase); } private void LogMissingShaders() { if (!Plugin.VRConfig.enableDebug.Value) { return; } foreach (KeyValuePair<string, Shader> missingShader in MissingShaders) { Plugin.Logger.LogWarning((object)"-------------------"); Plugin.Logger.LogError((object)("Missing VR Variant for Shader: " + ((Object)missingShader.Value).name)); } } private void ReplaceMaterialsFor<TRenderer>(IEnumerable<TRenderer> renderers) where TRenderer : Renderer { Dictionary<Material, Material> dictionary = new Dictionary<Material, Material>(); foreach (TRenderer renderer in renderers) { Material[] sharedMaterials = ((Renderer)renderer).sharedMaterials; if (sharedMaterials == null) { continue; } for (int i = 0; i < sharedMaterials.Length; i++) { Material val = sharedMaterials[i]; if (!IsValidOriginal(val)) { continue; } Shader val2 = ResolveShader(((Object)val.shader).name); if (!((Object)(object)val2 == (Object)null)) { if (!dictionary.TryGetValue(val, out var value)) { value = (dictionary[val] = CreateVRMaterial(val, val2)); } sharedMaterials[i] = value; } } ((Renderer)renderer).sharedMaterials = sharedMaterials; ((Renderer)renderer).materials = sharedMaterials; } } public static void ForceDetailRefresh(Terrain terrain) { TerrainData terrainData = terrain.terrainData; typeof(TerrainData).GetMethod("RefreshPrototypes", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(terrainData, null); for (int i = 0; i < terrainData.detailPrototypes.Length; i++) { int[,] detailLayer = terrainData.GetDetailLayer(0, 0, terrainData.detailWidth, terrainData.detailHeight, i); terrainData.SetDetailLayer(0, 0, i, detailLayer); } } public void CacheBaseGameShaders() { Plugin.Logger.LogInfo((object)"Scanning for base‑game HDRP + Shader Graph shaders..."); Shader[] array = Resources.FindObjectsOfTypeAll<Shader>(); foreach (Shader val in array) { if ((Object)(object)val == (Object)null) { continue; } string name = ((Object)val).name; bool num = name.StartsWith("HDRP/", StringComparison.OrdinalIgnoreCase); bool flag = name.StartsWith("Shader Graphs/", StringComparison.OrdinalIgnoreCase); if (!num && !flag) { continue; } int instanceID = ((Object)val).GetInstanceID(); if (instanceID <= 0) { continue; } if (!BaseGameHDRPShaders.TryGetValue(name, out var value)) { BaseGameHDRPShaders[name] = val; Plugin.Logger.LogInfo((object)$"Cached base‑game shader: {name} (ID {instanceID})"); continue; } int instanceID2 = ((Object)value).GetInstanceID(); if (instanceID2 <= 0 || instanceID < instanceID2) { BaseGameHDRPShaders[name] = val; Plugin.Logger.LogInfo((object)$"Updated base‑game shader: {name} → lower ID {instanceID} (was {instanceID2})"); } } Plugin.Logger.LogInfo((object)$"Captured {BaseGameHDRPShaders.Count} base‑game shaders."); } } namespace VRShaderFix { [HarmonyPatch] internal class Patches { [HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")] [HarmonyPostfix] public static void StartVRShaderFixViaPatch() { Plugin.Logger.LogDebug((object)"VR Shader Fix Applying"); Plugin.ShaderFixHost.StartShaderFix(); Plugin.Logger.LogDebug((object)"VR Shader Fix Applied"); } [HarmonyPatch(typeof(StartOfRound), "OnShipLandedMiscEvents")] [HarmonyPostfix] public static void StartVRShaderFixViaPatchBackup2() { Plugin.Logger.LogDebug((object)"VR Shader Fix Backup Call"); Plugin.ShaderFixHost.StartShaderFix(); Plugin.Logger.LogDebug((object)"VR Shader Fix Backup Call End"); } } [BepInPlugin("TKronix.VRShaderFix", "VRShaderFix", "1.0.0.0")] public class Plugin : BaseUnityPlugin { private const string GUID = "TKronix.VRShaderFix"; private const string NAME = "VRShaderFix"; private const string VERSION = "1.0.0.0"; private static int PressCount; internal static ManualLogSource Logger { get; private set; } public static ShaderFix ShaderFixHost { get; private set; } internal static VRSFConfig VRConfig { get; private set; } private void Awake() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin loading"); VRConfig = new VRSFConfig(((BaseUnityPlugin)this).Config); InputAction val = new InputAction("RunVRShaderFix", (InputActionType)1, "<Keyboard>/f1", (string)null, (string)null, (string)null); InputAction val2 = new InputAction("RunVRShaderFix2", (InputActionType)1, "<Keyboard>/f2", (string)null, (string)null, (string)null); val.performed += delegate { ShaderFixHost.StartShaderFix(); }; val2.performed += delegate { Hotkey2(); }; val.Disable(); val2.Disable(); if (VRConfig.enableDebug.Value) { val.Enable(); val2.Enable(); } SceneManager.sceneLoaded += InitalizeVRShaderFix; if (VRConfig.enableHarmonyPatches.Value) { new Harmony("TKronix.VRShaderFix").PatchAll(typeof(Patches)); Logger.LogInfo((object)"Plugin Harmony Patches Applied!"); } Logger.LogInfo((object)"Plugin loaded!"); } private void InitalizeVRShaderFix(Scene scene, LoadSceneMode mode) { //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_0027: Expected O, but got Unknown if (!((Scene)(ref scene)).name.Equals("SampleSceneRelay", StringComparison.OrdinalIgnoreCase)) { return; } GameObject val = new GameObject("VRShaderFixHost"); Object.DontDestroyOnLoad((Object)val); ShaderFixHost = val.AddComponent<ShaderFix>(); ShaderFixHost.CacheBaseGameShaders(); AssetBundle val2 = LoadAssetBundle("vrmaterials"); Material[] array = val2.LoadAllAssets<Material>(); foreach (Material val3 in array) { if (!((Object)(object)val3 == (Object)null)) { Logger.LogInfo((object)("Loaded Material: " + ((Object)val3).name)); ShaderFixHost.CustomShaders.Add(((Object)val3.shader).name, val3.shader); } } ShaderFixHost.CachedBlacklist = (from s in VRConfig.blacklistedScenes.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet<string>(StringComparer.OrdinalIgnoreCase); val2.Unload(false); val2 = null; SceneManager.sceneLoaded -= InitalizeVRShaderFix; SceneManager.sceneLoaded += ApplyVRFixOnSceneLoad; ShaderFixHost.StartShaderFix(); } private void CheckScene(Scene scene, LoadSceneMode mode) { if (((Scene)(ref scene)).name.Equals("SampleSceneRelay", StringComparison.OrdinalIgnoreCase)) { SceneManager.sceneLoaded += ApplyVRFixOnSceneLoad; SceneManager.sceneLoaded -= CheckScene; } } private void ApplyVRFixOnSceneLoad(Scene scene, LoadSceneMode mode) { if (VRConfig.enableLogSceneToConsole.Value) { string text = "Use name below for Blacklisting"; string name = ((Scene)(ref scene)).name; int num = Mathf.Max(text.Length, name.Length) + 6; string text2 = "╔" + new string('═', num) + "╗"; string text3 = "║" + Center(text, num) + "║"; string text4 = "║" + Center(name, num) + "║"; string text5 = "╚" + new string('═', num) + "╝"; Logger.LogInfo((object)text2); Logger.LogInfo((object)text3); Logger.LogInfo((object)text4); Logger.LogInfo((object)text5); } if (((Scene)(ref scene)).name.Equals("MainMenu", StringComparison.OrdinalIgnoreCase)) { SceneManager.sceneLoaded -= ApplyVRFixOnSceneLoad; SceneManager.sceneLoaded += CheckScene; } else { ShaderFixHost.StartShaderFix(); } } private string Center(string text, int totalWidth) { int num = totalWidth - text.Length; int num2 = num / 2; int count = num - num2; return new string(' ', num2) + text + new string(' ', count); } private AssetBundle LoadAssetBundle(string AssetBundle) { return AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), AssetBundle)); } private static void Hotkey2() { PressCount++; if (PressCount == 1) { Object.FindObjectOfType<PreInitSceneScript>().ChooseLaunchOption(true); } if (PressCount == 2) { Object.FindObjectOfType<MenuManager>().StartHosting(); } if (PressCount == 3) { StartOfRound.Instance.ChangeLevel(17); } if (PressCount == 4) { Object.FindObjectOfType<StartMatchLever>().StartGame(); } } } internal class VRSFConfig { public readonly ConfigEntry<bool> enableBlacklist; public readonly ConfigEntry<bool> enableLogSceneToConsole; public readonly ConfigEntry<string> blacklistedScenes; public readonly ConfigEntry<bool> enableHarmonyPatches; public readonly ConfigEntry<bool> enableDebug; public VRSFConfig(ConfigFile cfg) { enableLogSceneToConsole = cfg.Bind<bool>("Blacklist", "EnableLogSceneNameToConsole", false, "Enable or disable Logging of Scene Name to Console"); enableBlacklist = cfg.Bind<bool>("Blacklist", "EnableBlacklist", false, "Enable or disable the scene blacklist system"); blacklistedScenes = cfg.Bind<string>("Blacklist", "BlacklistedScenes", "ExampleSceneName1, ExampleSceneName2", "List of scene names to NOT replace shaders/materials on.\n(Separated by commas)"); enableHarmonyPatches = cfg.Bind<bool>("HarmonyPatches", "EnableHarmonyPatches", true, "Enable or disable the Harmony Patches"); enableDebug = cfg.Bind<bool>("Development", "EnableDevelopmentFeatures", false, "Enable or disable Dvelopment features \n(Ignore this its for Development Purposes Only nothing useful for Gameplay)"); } } } namespace VRShaderFix.utils { public static class MaterialUtils { public static void CopyMaterialProperties(Material source, Material target) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected I4, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null || (Object)(object)target == (Object)null) { return; } target.renderQueue = source.renderQueue; target.globalIlluminationFlags = source.globalIlluminationFlags; CopyShaderKeywords(source, target); Shader shader = source.shader; int propertyCount = shader.GetPropertyCount(); for (int i = 0; i < propertyCount; i++) { string propertyName = shader.GetPropertyName(i); ShaderPropertyType propertyType = shader.GetPropertyType(i); if (!target.HasProperty(propertyName)) { continue; } switch ((int)propertyType) { case 0: target.SetColor(propertyName, source.GetColor(propertyName)); break; case 1: target.SetVector(propertyName, source.GetVector(propertyName)); break; case 2: case 3: target.SetFloat(propertyName, source.GetFloat(propertyName)); break; case 4: { Texture texture = source.GetTexture(propertyName); target.SetTexture(propertyName, texture); if ((Object)(object)texture != (Object)null) { target.SetTextureOffset(propertyName, source.GetTextureOffset(propertyName)); target.SetTextureScale(propertyName, source.GetTextureScale(propertyName)); } break; } } } CopyMainTextureShortcuts(source, target); } private static void CopyShaderKeywords(Material source, Material target) { HashSet<string> hashSet = new HashSet<string>(source.shaderKeywords); string[] shaderKeywords = target.shaderKeywords; foreach (string item in shaderKeywords) { hashSet.Add(item); } target.shaderKeywords = hashSet.ToArray(); } private static void CopyMainTextureShortcuts(Material source, Material target) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (target.HasProperty("_MainTex")) { target.mainTexture = source.mainTexture; target.mainTextureOffset = source.mainTextureOffset; target.mainTextureScale = source.mainTextureScale; } } } public static class VRFixUtils { private static readonly string[] DefaultExcludedScenes = new string[3] { "MainMenu", "DontDestroyOnLoad", "HideAndDontSave" }; public static List<T> FindAllInLoadedScenes<T>(params string[] excludedScenes) where T : Component { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (excludedScenes == null || excludedScenes.Length == 0) { excludedScenes = DefaultExcludedScenes; } List<T> list = new List<T>(); int sceneCount = SceneManager.sceneCount; for (int i = 0; i < sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (((Scene)(ref sceneAt)).isLoaded && !excludedScenes.Contains(((Scene)(ref sceneAt)).name)) { GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { list.AddRange(val.GetComponentsInChildren<T>(true)); } } } return list; } public static Shader FindClosestShader(string name, Dictionary<string, Shader> shaders) { Shader result = null; int num = -1; foreach (KeyValuePair<string, Shader> shader in shaders) { string key = shader.Key; if ((key.StartsWith(name, StringComparison.OrdinalIgnoreCase) || name.StartsWith(key, StringComparison.OrdinalIgnoreCase)) && key.Length > num) { num = key.Length; result = shader.Value; } } return result; } } }