Decompiled source of MaterialAssetRestorerCore v2.0.0

Sniper1_1.MaterialAssetRestorerCore.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using LethalNetworkAPI;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.VFX;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("DunGen")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")]
[assembly: IgnoresAccessChecksTo("Unity.XR.Management")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")]
[assembly: AssemblyCompany("Sniper1_1.MaterialAssetRestorerCore")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0+388e20f91116320c11909ea84229296db8ae0927")]
[assembly: AssemblyProduct("MaterialAssetRestorerCore")]
[assembly: AssemblyTitle("Sniper1_1.MaterialAssetRestorerCore")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 MaterialAssetRestorerCore
{
	[BepInPlugin("Sniper1_1.MaterialAssetRestorerCore", "MaterialAssetRestorerCore", "2.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class MaterialAssetRestorerCore : BaseUnityPlugin
	{
		public static MaterialAssetRestorerCore Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static Harmony? Harmony { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			MaterialsNetworkSync.InitializeNetworkVariables();
			Patch();
			Logger.LogInfo((object)"Sniper1_1.MaterialAssetRestorerCore v2.0.0 has loaded!");
			Logger.LogInfo((object)"Oh hi, M.A.R.C.");
		}

		internal static void Patch()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("Sniper1_1.MaterialAssetRestorerCore");
			}
			Logger.LogDebug((object)"Patching...");
			Harmony.PatchAll(typeof(MaterialInit));
			Harmony.PatchAll(typeof(MaterialSwap));
			Harmony.PatchAll(typeof(MARCLeverPatchClass));
			JSONManager.ReadJSONFiles();
			Logger.LogDebug((object)"Finished patching!");
		}

		internal static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}
	}
	public class JSONManager
	{
		private class MaterialSetsWrapper
		{
			public List<MaterialInformationContainer> MaterialSets { get; set; }
		}

		public static void ReadJSONFiles()
		{
			DirectoryInfo parent = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.Parent;
			DirectoryInfo[] directories = parent.GetDirectories("MaterialReplacements", SearchOption.AllDirectories);
			if (directories.Length == 0)
			{
				MaterialAssetRestorerCore.Logger.LogWarning((object)"Could not find MaterialReplacements in plugins folder.");
				return;
			}
			MaterialAssetRestorerCore.Logger.LogDebug((object)("Found MaterialReplacements in plugins folder with " + directories.Length + " files."));
			DirectoryInfo[] array = directories;
			foreach (DirectoryInfo directoryInfo in array)
			{
				FileInfo[] files = directoryInfo.GetFiles("*.json", SearchOption.AllDirectories);
				foreach (FileInfo fileInfo in files)
				{
					MaterialAssetRestorerCore.Logger.LogDebug((object)("Reading JSON file: " + fileInfo.FullName));
					try
					{
						string text = File.ReadAllText(fileInfo.FullName, Encoding.UTF8);
						MaterialSetsWrapper materialSetsWrapper = JsonConvert.DeserializeObject<MaterialSetsWrapper>(text);
						if (materialSetsWrapper == null || materialSetsWrapper.MaterialSets.Count == 0)
						{
							MaterialAssetRestorerCore.Logger.LogWarning((object)("No material sets found in JSON file '" + fileInfo.Name + "', skipping."));
							continue;
						}
						foreach (MaterialInformationContainer materialSet in materialSetsWrapper.MaterialSets)
						{
							if (string.IsNullOrEmpty(materialSet.BaseMaterial))
							{
								MaterialAssetRestorerCore.Logger.LogWarning((object)("Skipping entry in '" + fileInfo.Name + "': missing 'BaseMaterial'."));
								continue;
							}
							if (string.IsNullOrEmpty(materialSet.ReplaceMaterial))
							{
								MaterialAssetRestorerCore.Logger.LogWarning((object)("Skipping entry in '" + fileInfo.Name + "': missing 'ReplaceMaterial'."));
								continue;
							}
							if (string.IsNullOrEmpty(materialSet.PrefabName) && string.IsNullOrEmpty(materialSet.SceneName))
							{
								MaterialAssetRestorerCore.Logger.LogWarning((object)("Skipping entry in '" + fileInfo.Name + "': While both aren't needed, either a valid 'PrefabName' or 'SceneName' is required."));
								continue;
							}
							if ((materialSet.MaterialSource.Value == MaterialInformationContainer.MaterialType.VFX && materialSet.MaterialDestination.Value != MaterialInformationContainer.MaterialType.VFX) || (materialSet.MaterialDestination.Value == MaterialInformationContainer.MaterialType.VFX && materialSet.MaterialSource.Value != MaterialInformationContainer.MaterialType.VFX))
							{
								MaterialAssetRestorerCore.Logger.LogWarning((object)("Skipping entry in '" + fileInfo.Name + "': VFX must be paired with VFX"));
								continue;
							}
							if (materialSet.MaterialSource.Value == MaterialInformationContainer.MaterialType.TerrainDetail && string.IsNullOrEmpty(materialSet.SceneName))
							{
								MaterialAssetRestorerCore.Logger.LogWarning((object)("Skipping entry in '" + fileInfo.Name + "': TerrainDetails as a 'MaterialSource' must have a valid 'SceneName'"));
								continue;
							}
							MaterialInit.materialInformationContainers.Add(materialSet);
							MaterialAssetRestorerCore.Logger.LogDebug((object)("Registered: '" + materialSet.BaseMaterial + "' -> '" + materialSet.ReplaceMaterial + "'" + ((materialSet.SceneName != null) ? (" in scene '" + materialSet.SceneName + "'") : "") + ((materialSet.PrefabName != null) ? (" from prefab '" + materialSet.PrefabName + "'") : "") + $" (Source: {materialSet.MaterialSource.Value}, Destination: {materialSet.MaterialDestination.Value})"));
						}
					}
					catch (Exception ex)
					{
						MaterialAssetRestorerCore.Logger.LogError((object)("Error reading JSON file '" + fileInfo.Name + "': " + ex.Message));
					}
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class MARCLeverPatchClass
	{
		private static string MARCDisabledHoverTip = "[ M.A.R.C. still caching materials! ]";

		private static string PreviousDisabledHoverTip = null;

		private static StartOfRound startOfRoundInstance = null;

		[HarmonyPatch(typeof(StartMatchLever), "Update")]
		[HarmonyPostfix]
		private static void LeverPatch(StartMatchLever __instance)
		{
			if (!MaterialsNetworkSync.MARCPatchingLever.Value)
			{
				return;
			}
			if ((Object)(object)startOfRoundInstance == (Object)null)
			{
				startOfRoundInstance = Object.FindObjectOfType<StartOfRound>();
			}
			if (__instance.triggerScript.disabledHoverTip != MARCDisabledHoverTip)
			{
				PreviousDisabledHoverTip = __instance.triggerScript.disabledHoverTip;
			}
			if (MaterialsNetworkSync.waitingPlayerCount.Value > 0)
			{
				__instance.triggerScript.disabledHoverTip = MARCDisabledHoverTip;
				__instance.triggerScript.interactable = false;
				return;
			}
			__instance.triggerScript.disabledHoverTip = PreviousDisabledHoverTip;
			if (((NetworkBehaviour)__instance).IsServer && startOfRoundInstance.inShipPhase && !startOfRoundInstance.travellingToNewLevel)
			{
				__instance.triggerScript.interactable = true;
			}
		}

		[HarmonyPatch(typeof(StartMatchLever), "Start")]
		[HarmonyPrefix]
		private static void SubscribeToLeverPull(StartMatchLever __instance)
		{
			if (MaterialsNetworkSync.MARCPatchingLever.Value)
			{
				MaterialAssetRestorerCore.Logger.LogDebug((object)"Subscribing to lever pull event");
				((UnityEvent<PlayerControllerB>)(object)__instance.triggerScript.onInteract).AddListener((UnityAction<PlayerControllerB>)OnLeverPulled);
			}
		}

		private static void OnLeverPulled(PlayerControllerB player)
		{
			MaterialsNetworkSync.MARCPatchingLever.Value = false;
			MaterialAssetRestorerCore.Logger.LogDebug((object)"Lever pulled, M.A.R.C. patching of lever disabled");
		}
	}
	[HarmonyPatch(typeof(StartMatchLever))]
	public class MaterialInit
	{
		public static List<MaterialInformationContainer> materialInformationContainers = new List<MaterialInformationContainer>();

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartMatchLever), "Start")]
		public static void InitializeMaterialsPatch()
		{
			((MonoBehaviour)CoroutineHelper.Instance).StartCoroutine(InitializeMaterialsCoroutine());
		}

		public static IEnumerator InitializeMaterialsCoroutine()
		{
			if (!MaterialsNetworkSync.waitingPlayerCount.IsInitialized)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => MaterialsNetworkSync.waitingPlayerCount.IsInitialized));
			}
			LNetworkVariable<int> waitingPlayerCount = MaterialsNetworkSync.waitingPlayerCount;
			int value = waitingPlayerCount.Value;
			waitingPlayerCount.Value = value + 1;
			SceneLoadPatches.MuteSceneStateChangeEvents();
			MaterialAssetRestorerCore.Logger.LogInfo((object)"Initializing materials...");
			foreach (MaterialInformationContainer container in materialInformationContainers)
			{
				yield return MaterialGet.GET_material(container.BaseMaterial, container.PrefabName, container.SceneName, container.MaterialSource, delegate(Object foundMaterial)
				{
					if (foundMaterial != (Object)null)
					{
						container.replacementMaterial = foundMaterial;
					}
				});
			}
			SceneLoadPatches.UnmuteSceneStateChangeEvents();
			MaterialAssetRestorerCore.Logger.LogInfo((object)"Finished initializing materials.");
			LNetworkVariable<int> waitingPlayerCount2 = MaterialsNetworkSync.waitingPlayerCount;
			value = waitingPlayerCount2.Value;
			waitingPlayerCount2.Value = value - 1;
		}
	}
	[HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")]
	public class MaterialSwap
	{
		[HarmonyPostfix]
		public static void SwapMaterials(RoundManager __instance)
		{
			//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)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Scene sceneByName = SceneManager.GetSceneByName(__instance.currentLevel.sceneName);
			foreach (MaterialInformationContainer materialInformationContainer in MaterialInit.materialInformationContainers)
			{
				if (materialInformationContainer.replacementMaterial != (Object)null)
				{
					MaterialSet.SET_material(materialInformationContainer.ReplaceMaterial, materialInformationContainer.replacementMaterial, sceneByName, materialInformationContainer.MaterialDestination);
				}
			}
		}
	}
	public class MaterialInformationContainer
	{
		public enum MaterialType
		{
			Renderer,
			TerrainDetail,
			ParticleSystem,
			VFX
		}

		public string BaseMaterial = null;

		public string ReplaceMaterial = null;

		public string PrefabName = null;

		public string SceneName = null;

		public Object replacementMaterial = null;

		public MaterialType? MaterialSource = MaterialType.Renderer;

		public MaterialType? MaterialDestination = MaterialType.Renderer;

		public MaterialInformationContainer(string materialToFindName, string materialToReplaceName, string prefabToSearchName, string sceneToSearchName, Material replacementMaterial, MaterialType materialSource, MaterialType materialDestination)
		{
			BaseMaterial = materialToFindName;
			ReplaceMaterial = materialToReplaceName;
			PrefabName = prefabToSearchName;
			SceneName = sceneToSearchName;
			this.replacementMaterial = (Object)(object)replacementMaterial;
			MaterialSource = materialSource;
			MaterialDestination = materialDestination;
		}
	}
	[HarmonyPatch(typeof(SceneManager))]
	public class SceneLoadPatches
	{
		public static void MuteSceneStateChangeEvents()
		{
			Harmony? harmony = MaterialAssetRestorerCore.Harmony;
			if (harmony != null)
			{
				harmony.PatchAll(typeof(SceneLoadPatches));
			}
			MaterialAssetRestorerCore.Logger.LogDebug((object)"Suppressed scene load/unload events from triggering.");
		}

		public static void UnmuteSceneStateChangeEvents()
		{
			Harmony? harmony = MaterialAssetRestorerCore.Harmony;
			if (harmony != null)
			{
				harmony.Unpatch((MethodBase)AccessTools.Method(typeof(SceneManager), "Internal_SceneLoaded", (Type[])null, (Type[])null), (HarmonyPatchType)0, MaterialAssetRestorerCore.Harmony.Id);
			}
			Harmony? harmony2 = MaterialAssetRestorerCore.Harmony;
			if (harmony2 != null)
			{
				harmony2.Unpatch((MethodBase)AccessTools.Method(typeof(SceneManager), "Internal_SceneUnloaded", (Type[])null, (Type[])null), (HarmonyPatchType)0, MaterialAssetRestorerCore.Harmony.Id);
			}
			MaterialAssetRestorerCore.Logger.LogDebug((object)"Re-enabled scene load/unload events.");
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		[HarmonyPatch("Internal_SceneLoaded")]
		public static bool MuteSceneLoadedEventTrigger()
		{
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		[HarmonyPatch("Internal_SceneUnloaded")]
		public static bool MuteSceneUnloadedEventTrigger()
		{
			return false;
		}
	}
	public class MaterialGet
	{
		public static IEnumerator GET_material(string materialToFind, string prefabToSearch = null, string sceneToSearch = null, MaterialInformationContainer.MaterialType? materialSource = null, Action<Object> onComplete = null)
		{
			Object materialToReturn = null;
			if (string.IsNullOrEmpty(materialToFind))
			{
				MaterialAssetRestorerCore.Logger.LogWarning((object)"Material to find is null.");
				onComplete?.Invoke(null);
				yield break;
			}
			if (!string.IsNullOrEmpty(prefabToSearch))
			{
				GameObject[] objects = Resources.FindObjectsOfTypeAll<GameObject>();
				GameObject[] array = objects;
				foreach (GameObject prefab in array)
				{
					if (((Object)prefab).name == prefabToSearch)
					{
						MaterialAssetRestorerCore.Logger.LogDebug((object)("Found a prefab '" + prefabToSearch + "'."));
						if (!materialSource.HasValue || materialSource == MaterialInformationContainer.MaterialType.Renderer)
						{
							materialToReturn = (Object)(object)GetFromRenderers(prefab, materialToFind);
						}
						if (materialSource == MaterialInformationContainer.MaterialType.ParticleSystem)
						{
							materialToReturn = (Object)(object)GetFromParticleSystems(prefab, materialToFind);
						}
						if (materialSource == MaterialInformationContainer.MaterialType.TerrainDetail)
						{
							materialToReturn = (Object)(object)GetFromTerrainDetails(prefab, materialToFind);
						}
						if (materialSource == MaterialInformationContainer.MaterialType.VFX)
						{
							materialToReturn = (Object)(object)GetFromVFX(prefab, materialToFind);
						}
						if (materialToReturn != (Object)null)
						{
							break;
						}
					}
				}
			}
			else if (!string.IsNullOrEmpty(sceneToSearch))
			{
				Scene scene = SceneManager.GetSceneByName(sceneToSearch);
				if (sceneToSearch != "SampleSceneRelay" && !((Scene)(ref scene)).isLoaded)
				{
					MaterialAssetRestorerCore.Logger.LogDebug((object)("Attempting to access scene '" + sceneToSearch + "'."));
					yield return SceneManager.LoadSceneAsync(sceneToSearch, (LoadSceneMode)1);
					scene = SceneManager.GetSceneByName(sceneToSearch);
					MaterialAssetRestorerCore.Logger.LogDebug((object)$"Found scene '{sceneToSearch}'? {((Scene)(ref scene)).isLoaded}");
					if (!((Scene)(ref scene)).IsValid())
					{
						MaterialAssetRestorerCore.Logger.LogWarning((object)("Scene '" + sceneToSearch + "' not found."));
						onComplete?.Invoke(null);
						yield break;
					}
				}
				GameObject[] gameObjects = ((Scene)(ref scene)).GetRootGameObjects();
				GameObject[] array2 = gameObjects;
				foreach (GameObject gameObject in array2)
				{
					if (sceneToSearch != "SampleSceneRelay")
					{
						gameObject.SetActive(false);
					}
					if (!materialSource.HasValue || materialSource == MaterialInformationContainer.MaterialType.Renderer)
					{
						materialToReturn = (Object)(object)GetFromRenderers(gameObject, materialToFind);
					}
					if (materialSource == MaterialInformationContainer.MaterialType.ParticleSystem)
					{
						materialToReturn = (Object)(object)GetFromParticleSystems(gameObject, materialToFind);
					}
					if (materialSource == MaterialInformationContainer.MaterialType.TerrainDetail)
					{
						materialToReturn = (Object)(object)GetFromTerrainDetails(gameObject, materialToFind);
					}
					if (materialSource == MaterialInformationContainer.MaterialType.VFX)
					{
						materialToReturn = (Object)(object)GetFromVFX(gameObject, materialToFind);
					}
					if (materialToReturn != (Object)null)
					{
						break;
					}
				}
				if (sceneToSearch != "SampleSceneRelay" && ((Scene)(ref scene)).isLoaded)
				{
					yield return SceneManager.UnloadSceneAsync(scene);
					MaterialAssetRestorerCore.Logger.LogDebug((object)("Unloaded scene '" + sceneToSearch + "'."));
				}
			}
			MaterialAssetRestorerCore.Logger.LogInfo((object)("Material '" + materialToFind + "' search completed. Found: " + ((materialToReturn != (Object)null) ? "Yes" : "No")));
			onComplete?.Invoke(materialToReturn);
		}

		private static Material GetFromRenderers(GameObject objToSearch, string materialToFind)
		{
			Renderer[] componentsInChildren = objToSearch.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val.sharedMaterial != (Object)null && ((Object)val.sharedMaterial).name == materialToFind && ((Object)val.sharedMaterial.shader).name != "Hidden/InternalErrorShader")
				{
					MaterialAssetRestorerCore.Logger.LogDebug((object)("Found material '" + materialToFind + "' in '" + ((Object)objToSearch).name + "''s renderers."));
					return val.sharedMaterial;
				}
			}
			return null;
		}

		private static Material GetFromParticleSystems(GameObject objToSearch, string materialToFind)
		{
			ParticleSystemRenderer[] componentsInChildren = objToSearch.GetComponentsInChildren<ParticleSystemRenderer>(true);
			foreach (ParticleSystemRenderer val in componentsInChildren)
			{
				if ((Object)(object)((Renderer)val).sharedMaterial != (Object)null && ((Object)((Renderer)val).sharedMaterial).name == materialToFind && ((Object)((Renderer)val).sharedMaterial.shader).name != "Hidden/InternalErrorShader")
				{
					MaterialAssetRestorerCore.Logger.LogDebug((object)("Found material '" + materialToFind + "' in '" + ((Object)objToSearch).name + "''s particle systems."));
					return ((Renderer)val).sharedMaterial;
				}
			}
			return null;
		}

		private static Material GetFromTerrainDetails(GameObject objToSearch, string materialToFind)
		{
			Terrain[] componentsInChildren = objToSearch.GetComponentsInChildren<Terrain>(true);
			foreach (Terrain val in componentsInChildren)
			{
				DetailPrototype[] detailPrototypes = val.terrainData.detailPrototypes;
				foreach (DetailPrototype val2 in detailPrototypes)
				{
					if (!((Object)(object)val2.prototype != (Object)null))
					{
						continue;
					}
					Renderer[] componentsInChildren2 = val2.prototype.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val3 in componentsInChildren2)
					{
						if ((Object)(object)val3.sharedMaterial != (Object)null && ((Object)val3.sharedMaterial).name == materialToFind && ((Object)val3.sharedMaterial.shader).name != "Hidden/InternalErrorShader")
						{
							MaterialAssetRestorerCore.Logger.LogDebug((object)("Found material '" + materialToFind + "' in '" + ((Object)objToSearch).name + "'s detail prototype."));
							return val3.sharedMaterial;
						}
					}
				}
			}
			return null;
		}

		private static VisualEffectAsset GetFromVFX(GameObject objToSearch, string materialToFind)
		{
			VisualEffect[] componentsInChildren = objToSearch.GetComponentsInChildren<VisualEffect>(true);
			foreach (VisualEffect val in componentsInChildren)
			{
				if ((Object)(object)val.visualEffectAsset != (Object)null && ((Object)val.visualEffectAsset).name == materialToFind)
				{
					MaterialAssetRestorerCore.Logger.LogDebug((object)("Found vfx '" + materialToFind + "' in '" + ((Object)objToSearch).name + "''s visual effects."));
					return val.visualEffectAsset;
				}
			}
			return null;
		}
	}
	public class MaterialSet
	{
		public static void SET_material(string original, Object replacement, Scene sceneToReplace, MaterialInformationContainer.MaterialType? materialDestination = null)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_0496: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Expected O, but got Unknown
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Expected O, but got Unknown
			GameObject[] rootGameObjects = ((Scene)(ref sceneToReplace)).GetRootGameObjects();
			foreach (GameObject val in rootGameObjects)
			{
				if (!materialDestination.HasValue || materialDestination == MaterialInformationContainer.MaterialType.Renderer)
				{
					Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val2 in componentsInChildren)
					{
						Material[] sharedMaterials = val2.sharedMaterials;
						bool flag = false;
						for (int k = 0; k < sharedMaterials.Length; k++)
						{
							if ((Object)(object)sharedMaterials[k] != (Object)null && ((Object)sharedMaterials[k]).name == original)
							{
								sharedMaterials[k] = (Material)replacement;
								flag = true;
								MaterialAssetRestorerCore.Logger.LogInfo((object)("Replaced material '" + original + "' with '" + replacement.name + "' in renderer '" + ((Object)((Component)val2).gameObject).name + "' in scene '" + ((Scene)(ref sceneToReplace)).name + "'."));
							}
						}
						if (flag)
						{
							val2.sharedMaterials = sharedMaterials;
						}
					}
				}
				else if (materialDestination == MaterialInformationContainer.MaterialType.ParticleSystem)
				{
					ParticleSystem[] componentsInChildren2 = val.GetComponentsInChildren<ParticleSystem>(true);
					foreach (ParticleSystem val3 in componentsInChildren2)
					{
						ParticleSystemRenderer component = ((Component)val3).GetComponent<ParticleSystemRenderer>();
						if (!((Object)(object)component != (Object)null))
						{
							continue;
						}
						Material[] sharedMaterials2 = ((Renderer)component).sharedMaterials;
						bool flag2 = false;
						for (int m = 0; m < sharedMaterials2.Length; m++)
						{
							if ((Object)(object)sharedMaterials2[m] != (Object)null && ((Object)sharedMaterials2[m]).name == original)
							{
								sharedMaterials2[m] = (Material)replacement;
								flag2 = true;
								MaterialAssetRestorerCore.Logger.LogInfo((object)("Replaced material '" + original + "' with '" + replacement.name + "' in particle system '" + ((Object)((Component)val3).gameObject).name + "' in scene '" + ((Scene)(ref sceneToReplace)).name + "'."));
							}
						}
						if (flag2)
						{
							((Renderer)component).sharedMaterials = sharedMaterials2;
						}
					}
				}
				if (materialDestination == MaterialInformationContainer.MaterialType.TerrainDetail)
				{
					Terrain[] componentsInChildren3 = val.GetComponentsInChildren<Terrain>(true);
					foreach (Terrain val4 in componentsInChildren3)
					{
						TerrainData terrainData = val4.terrainData;
						if (!((Object)(object)terrainData != (Object)null))
						{
							continue;
						}
						DetailPrototype[] detailPrototypes = terrainData.detailPrototypes;
						bool flag3 = false;
						for (int num = 0; num < detailPrototypes.Length; num++)
						{
							if (!((Object)(object)detailPrototypes[num].prototype != (Object)null))
							{
								continue;
							}
							Material[] sharedMaterials3 = detailPrototypes[num].prototype.GetComponent<Renderer>().sharedMaterials;
							for (int num2 = 0; num2 < sharedMaterials3.Length; num2++)
							{
								if ((Object)(object)sharedMaterials3[num2] != (Object)null && ((Object)sharedMaterials3[num2]).name == original)
								{
									sharedMaterials3[num2] = (Material)replacement;
									flag3 = true;
									MaterialAssetRestorerCore.Logger.LogInfo((object)("Replaced material '" + original + "' with '" + replacement.name + "' in terrain detail '" + ((Object)detailPrototypes[num].prototype).name + "' in scene '" + ((Scene)(ref sceneToReplace)).name + "'."));
								}
							}
							if (flag3)
							{
								detailPrototypes[num].prototype.GetComponent<Renderer>().sharedMaterials = sharedMaterials3;
								terrainData.RefreshPrototypes();
							}
						}
					}
				}
				if (materialDestination != MaterialInformationContainer.MaterialType.VFX)
				{
					continue;
				}
				VisualEffect[] componentsInChildren4 = val.GetComponentsInChildren<VisualEffect>(true);
				foreach (VisualEffect val5 in componentsInChildren4)
				{
					bool flag4 = false;
					if ((Object)(object)val5 != (Object)null && (Object)(object)val5.visualEffectAsset != (Object)null && ((Object)val5.visualEffectAsset).name == original)
					{
						val5.visualEffectAsset = (VisualEffectAsset)replacement;
						val5.Reinit();
						flag4 = true;
						MaterialAssetRestorerCore.Logger.LogInfo((object)("Replaced vfx '" + original + "' with '" + replacement.name + "' in vfx '" + ((Object)val5).name + "' in scene '" + ((Scene)(ref sceneToReplace)).name + "'."));
					}
				}
			}
		}
	}
	internal static class MaterialsNetworkSync
	{
		internal static LNetworkVariable<int> waitingPlayerCount = LNetworkVariable<int>.Connect("waitingPlayerCount", 0, (LNetworkVariableWritePerms)2, (Action<int, int>)OnWaitingPlayerCountChanged);

		internal static LNetworkVariable<bool> MARCPatchingLever = LNetworkVariable<bool>.Connect("MARCPatchingLever", true, (LNetworkVariableWritePerms)2, (Action<bool, bool>)OnMARCPatchingLeverChanged);

		private static void OnWaitingPlayerCountChanged(int oldValue, int newValue)
		{
			MaterialAssetRestorerCore.Logger.LogWarning((object)$"M.A.R.C. Waiting player count changed from {oldValue} to {newValue}");
			if (newValue <= 0)
			{
				MaterialAssetRestorerCore.Logger.LogDebug((object)"Pull the lever, Kronk!");
				return;
			}
			MARCPatchingLever.Value = true;
			MaterialAssetRestorerCore.Logger.LogDebug((object)"Wrong lever!");
		}

		private static void OnMARCPatchingLeverChanged(bool oldValue, bool newValue)
		{
			MaterialAssetRestorerCore.Logger.LogWarning((object)$"M.A.R.C. MARCPatchingLever changed from {oldValue} to {newValue}");
		}

		internal static void InitializeNetworkVariables()
		{
			MaterialAssetRestorerCore.Logger.LogDebug((object)"Initialized network variables");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Sniper1_1.MaterialAssetRestorerCore";

		public const string PLUGIN_NAME = "MaterialAssetRestorerCore";

		public const string PLUGIN_VERSION = "2.0.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}