Decompiled source of Chef Variants v1.0.1

plugins/ChefVariantsCompat.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using Microsoft.CodeAnalysis;
using RoR2;
using UnityEngine;

[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("ChefVariantsCompat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ChefVariantsCompat")]
[assembly: AssemblyTitle("ChefVariantsCompat")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 ChefVariantsCompat
{
	[BepInPlugin("com.kotchisaintmoon.chefvariantscompat", "Chef Variants Compatibility", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class ChefVariantsCompatPlugin : BaseUnityPlugin
	{
		private const string PluginGuid = "com.kotchisaintmoon.chefvariantscompat";

		private const string PluginName = "Chef Variants Compatibility";

		private const string PluginVersion = "1.0.1";

		private bool registrationAttempted;

		private void Awake()
		{
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(RegisterCompatibility));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded. Will register ChefMod's survivor as a variant of the official Chef after survivor catalogs load.");
		}

		private void OnDestroy()
		{
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(RegisterCompatibility));
		}

		private void RegisterCompatibility()
		{
			if (registrationAttempted)
			{
				return;
			}
			registrationAttempted = true;
			try
			{
				Type variantType = FindType("Survariants.SurvivorVariantDef");
				Type type = FindType("Survariants.SurvivorVariantCatalog");
				if (variantType == null || type == null)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Survariants API not found; compatibility is inactive.");
					return;
				}
				SurvivorDef val = SurvivorCatalog.allSurvivorDefs.FirstOrDefault((Func<SurvivorDef, bool>)IsOfficialChef);
				SurvivorDef val2 = SurvivorCatalog.allSurvivorDefs.FirstOrDefault((Func<SurvivorDef, bool>)IsClassicChef);
				if ((Object)(object)val == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not identify the official Seekers of the Storm Chef. No survivor was hidden or changed.");
					return;
				}
				if ((Object)(object)val2 == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not identify ChefMod's survivor. No survivor was hidden or changed.");
					return;
				}
				MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "AddSurvivorVariant" && method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType.IsAssignableFrom(variantType));
				if (methodInfo == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Survariants is installed, but its AddSurvivorVariant API was not found.");
				}
				else
				{
					RegisterVariant(methodInfo, variantType, val, val2);
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to register Classic Chef: {arg}");
			}
		}

		private static Type? FindType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(fullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		private static bool IsOfficialChef(SurvivorDef survivor)
		{
			string obj = survivor.cachedName ?? string.Empty;
			string text = (((Object)(object)survivor.bodyPrefab != (Object)null) ? ((Object)survivor.bodyPrefab).name : string.Empty);
			if (!obj.Equals("Chef", StringComparison.OrdinalIgnoreCase))
			{
				return text.Equals("ChefBody", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsClassicChef(SurvivorDef survivor)
		{
			string text = survivor.cachedName ?? string.Empty;
			string obj = (((Object)(object)survivor.bodyPrefab != (Object)null) ? ((Object)survivor.bodyPrefab).name : string.Empty);
			string text2 = ((!((Object)(object)survivor.bodyPrefab != (Object)null)) ? string.Empty : (survivor.bodyPrefab.GetComponent<CharacterBody>()?.baseNameToken ?? string.Empty));
			if (!obj.Equals("GnomeChefBody", StringComparison.OrdinalIgnoreCase) && !text.Equals("GnomeChef", StringComparison.OrdinalIgnoreCase))
			{
				return text2.Equals("GNOMECHEF_NAME", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private void RegisterVariant(MethodInfo addVariant, Type variantType, SurvivorDef targetSurvivor, SurvivorDef variantSurvivor)
		{
			try
			{
				ScriptableObject val = ScriptableObject.CreateInstance(variantType);
				((Object)val).name = "GnomeChefClassicVariant";
				SetMember(val, "DisplayName", "Classic Chef");
				SetMember(val, "VariantSurvivor", variantSurvivor);
				SetMember(val, "TargetSurvivor", targetSurvivor);
				SetMember(val, "Description", "The classic Chef joins the Seekers of the Storm Chef as a selectable variant.");
				if ((Object)(object)variantSurvivor.unlockableDef != (Object)null)
				{
					TrySetMember(val, "RequiredUnlock", variantSurvivor.unlockableDef);
				}
				addVariant.Invoke(null, new object[1] { val });
				variantSurvivor.hidden = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered Classic Chef as a variant of the official Chef.");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to register Classic Chef as an official Chef variant: {arg}");
			}
		}

		private static void SetMember(object target, string name, object value)
		{
			if (!TrySetMember(target, name, value))
			{
				throw new MissingMemberException(target.GetType().FullName, name);
			}
		}

		private static bool TrySetMember(object target, string name, object value)
		{
			Type type = target.GetType();
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
			if (property != null && property.CanWrite)
			{
				property.SetValue(target, value);
				return true;
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public);
			if (field != null)
			{
				field.SetValue(target, value);
				return true;
			}
			return false;
		}
	}
}