Decompiled source of ConcentricContent v1.0.1

ConcentricContent.dll

Decompiled 11 hours ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using EntityStates;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using RoR2;
using RoR2.ContentManagement;
using RoR2.Skills;
using RoR2.UI;
using UnityEngine;
using UnityEngine.UI;

[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: AssemblyCompany("ConcentricContent")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ConcentricContent")]
[assembly: AssemblyTitle("ConcentricContent")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace ConcentricContent
{
	public abstract class Concentric
	{
		public static readonly Dictionary<string, object> Objects = new Dictionary<string, object>();

		public static readonly Dictionary<Type, Concentric> Assets = new Dictionary<Type, Concentric>();

		public static readonly Dictionary<object, Concentric> ObjectToAssetMap = new Dictionary<object, Concentric>();

		public static readonly List<IOverlay> Overlays = new List<IOverlay>();

		public static readonly List<IMaterialSwap> MaterialSwaps = new List<IMaterialSwap>();

		public static readonly Dictionary<IMaterialSwap, Material> MaterialSwapMaterials = new Dictionary<IMaterialSwap, Material>();

		public static readonly Dictionary<IOverlay, Material> OverlayMaterials = new Dictionary<IOverlay, Material>();

		public static readonly ConcurrentDictionary<string, Task<object?>> Tasks = new ConcurrentDictionary<string, Task<object>>(Environment.ProcessorCount * 2, 64);

		public virtual bool Enabled => true;

		public static Task<ItemDef> GetItemDef<T>() where T : Concentric, IItem
		{
			return GetObjectOrThrow<T, IItem, ItemDef>();
		}

		public static async Task<ItemIndex> GetItemIndex<T>() where T : Concentric, IItem
		{
			return (await GetObjectOrThrow<T, IItem, ItemDef>()).itemIndex;
		}

		public static Task<UnlockableDef> GetUnlockableDef<T>() where T : Concentric, IUnlockable
		{
			return GetObjectOrThrow<T, IUnlockable, UnlockableDef>();
		}

		public static Task<BuffDef> GetBuffDef<T>() where T : Concentric, IBuff
		{
			return GetObjectOrThrow<T, IBuff, BuffDef>();
		}

		public static async Task<BuffIndex> GetBuffIndex<T>() where T : Concentric, IBuff
		{
			return (await GetObjectOrThrow<T, IBuff, BuffDef>()).buffIndex;
		}

		public static async Task<BodyIndex> GetBodyIndex<T>() where T : Concentric, IBody
		{
			return (await GetObjectOrThrow<T, IBody, GameObject>()).GetComponent<CharacterBody>().bodyIndex;
		}

		public static Task<Material> GetMaterial<T>() where T : Concentric, IMaterial
		{
			return GetObjectOrThrow<T, IMaterial, Material>();
		}

		public static Task<SurvivorDef> GetSurvivorDef<T>() where T : Concentric, ISurvivor
		{
			return GetObjectOrThrow<T, ISurvivor, SurvivorDef>();
		}

		public static Task<SkinDef> GetSkinDef<T>() where T : Concentric, ISkin
		{
			return GetObjectOrThrow<T, ISkin, SkinDef>();
		}

		public static Task<SkillDef> GetSkillDef<T>() where T : Concentric, ISkill
		{
			return GetObjectOrThrow<T, ISkill, SkillDef>();
		}

		public static Task<MusicTrackDef> GetMusicTrackDef<T>() where T : Concentric, IMusicTrack
		{
			return GetObjectOrThrow<T, IMusicTrack, MusicTrackDef>();
		}

		public static Task<SkillFamily> GetSkillFamily<T>() where T : Concentric, ISkillFamily
		{
			return GetObjectOrThrow<T, ISkillFamily, SkillFamily>();
		}

		public static Task<Variant> GetSkillFamilyVariant<T>() where T : Concentric, ISkill
		{
			return GetObjectOrThrow<IVariant, Variant>(GetAsset<T>());
		}

		public static Task<GameObject> GetNetworkedObject<T>() where T : Concentric, INetworkedObject
		{
			return GetObjectOrThrow<T, INetworkedObject, GameObject>();
		}

		public static Task<GameObject> GetGenericObject<T>() where T : Concentric, IGenericObject
		{
			return GetObjectOrThrow<T, IGenericObject, GameObject>();
		}

		public static Task<GameObject> GetProjectile<T>() where T : Concentric, IProjectile
		{
			return GetObjectOrThrow<T, IProjectile, GameObject>();
		}

		public static Task<GameObject> GetProjectileGhost<T>() where T : Concentric, IProjectileGhost
		{
			return GetObjectOrThrow<T, IProjectileGhost, GameObject>();
		}

		public static Task<GameObject> GetEffect<T>() where T : Concentric, IEffect
		{
			return GetObjectOrThrow<T, IEffect, GameObject>();
		}

		public static Task<GameObject> GetMaster<T>() where T : Concentric, IMaster
		{
			return GetObjectOrThrow<T, IMaster, GameObject>();
		}

		public static Task<GameObject> GetBody<T>() where T : Concentric, IBody
		{
			return GetObjectOrThrow<T, IBody, GameObject>();
		}

		public static Task<GameObject> GetBodyDisplay<T>() where T : Concentric, IBodyDisplay
		{
			return GetObjectOrThrow<T, IBodyDisplay, GameObject>();
		}

		public static Task<GameObject> GetModel<T>() where T : Concentric, IModel
		{
			return GetObjectOrThrow<T, IModel, GameObject>();
		}

		public static async Task<ContentPack> BuildContentPack(Assembly assembly)
		{
			ContentPack result = new ContentPack();
			Type[] types = assembly.GetTypes();
			foreach (Type barData in types.Where((Type x) => typeof(BarData).IsAssignableFrom(x) && !x.IsAbstract))
			{
				ExtraHealthBarSegments._barDataTypes.Add(barData);
			}
			IEnumerable<Type> assets = types.Where((Type x) => typeof(Concentric).IsAssignableFrom(x) && !x.IsAbstract);
			Dictionary<Type, Concentric> localAssets = assets.ToDictionary((Type x) => x, (Type x) => (Concentric)Activator.CreateInstance(x));
			foreach (var (key, value) in localAssets)
			{
				Assets[key] = value;
			}
			Concentric[] instances = localAssets.Values.Where((Concentric x) => x.Enabled).ToArray();
			await Task.WhenAll(instances.Select((Concentric asset) => asset.Initialize()));
			IOverlay[] overlays = instances.Where((Concentric x) => x is IOverlay).Cast<IOverlay>().ToArray();
			Overlays.AddRange(overlays);
			Material[] materialsOL = await Task.WhenAll(overlays.Select((IOverlay x) => GetObjectOrThrow<IOverlay, Material>((Concentric)x)));
			for (int i = 0; i < overlays.Length; i++)
			{
				OverlayMaterials[overlays[i]] = materialsOL[i];
			}
			MaterialSwaps.AddRange(instances.Where((Concentric x) => x is IMaterialSwap).Cast<IMaterialSwap>());
			IMaterialSwap[] swaps = instances.Where((Concentric x) => x is IMaterialSwap).Cast<IMaterialSwap>().ToArray();
			MaterialSwaps.AddRange(swaps);
			Material[] materialsSW = await Task.WhenAll(swaps.Select((IMaterialSwap x) => GetObjectOrThrow<IMaterialSwap, Material>((Concentric)x)));
			for (int j = 0; j < overlays.Length; j++)
			{
				MaterialSwapMaterials[swaps[j]] = materialsSW[j];
			}
			IEnumerable<Type> entityStates = instances.Where((Concentric x) => x is IEntityStates).SelectMany((Concentric x) => (Type[])Objects.GetOrSet(x.GetType().Assembly.FullName + "_" + x.GetType().FullName + "_EntityStates", () => ((IEntityStates)x).GetEntityStates()));
			NamedAssetCollection<UnlockableDef> unlockableDefs = result.unlockableDefs;
			unlockableDefs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is IUnlockable).Select(GetObjectOrThrow<IUnlockable, UnlockableDef>)));
			NamedAssetCollection<ItemDef> itemDefs = result.itemDefs;
			itemDefs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is IItem).Select(GetObjectOrThrow<IItem, ItemDef>)));
			NamedAssetCollection<BuffDef> buffDefs = result.buffDefs;
			buffDefs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is IBuff).Select(GetObjectOrThrow<IBuff, BuffDef>)));
			NamedAssetCollection<SkillDef> skillDefs = result.skillDefs;
			skillDefs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is ISkill).Select(GetObjectOrThrow<ISkill, SkillDef>)));
			result.entityStateTypes.Add(instances.Where((Concentric x) => x is ISkill).SelectMany((Concentric x) => (Type[])Objects[x.GetType().Assembly.FullName + "_" + x.GetType().FullName + "_ISkill_EntityStates"]).Concat(entityStates)
				.Distinct()
				.ToArray());
			NamedAssetCollection<SkillFamily> skillFamilies = result.skillFamilies;
			skillFamilies.Add(await Task.WhenAll(instances.Where((Concentric x) => x is ISkillFamily).Select(GetObjectOrThrow<ISkillFamily, SkillFamily>)));
			NamedAssetCollection<GameObject> networkedObjectPrefabs = result.networkedObjectPrefabs;
			networkedObjectPrefabs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is INetworkedObject).Select(GetObjectOrThrow<INetworkedObject, GameObject>)));
			NamedAssetCollection<GameObject> bodyPrefabs = result.bodyPrefabs;
			bodyPrefabs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is IBody).Select(GetObjectOrThrow<IBody, GameObject>)));
			NamedAssetCollection<SurvivorDef> survivorDefs = result.survivorDefs;
			survivorDefs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is ISurvivor).Select(GetObjectOrThrow<ISurvivor, SurvivorDef>)));
			NamedAssetCollection<GameObject> projectilePrefabs = result.projectilePrefabs;
			projectilePrefabs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is IProjectile).Select(GetObjectOrThrow<IProjectile, GameObject>)));
			NamedAssetCollection<EffectDef> effectDefs = result.effectDefs;
			effectDefs.Add(((IEnumerable<GameObject>)(await Task.WhenAll(instances.Where((Concentric x) => x is IEffect).Select(GetObjectOrThrow<IEffect, GameObject>)))).Select((Func<GameObject, EffectDef>)((GameObject x) => new EffectDef(x))).ToArray());
			NamedAssetCollection<GameObject> masterPrefabs = result.masterPrefabs;
			masterPrefabs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is IMaster).Select(GetObjectOrThrow<IMaster, GameObject>)));
			NamedAssetCollection<MusicTrackDef> musicTrackDefs = result.musicTrackDefs;
			musicTrackDefs.Add(await Task.WhenAll(instances.Where((Concentric x) => x is IMusicTrack).Select(GetObjectOrThrow<IMusicTrack, MusicTrackDef>)));
			return result;
		}

		public static bool TryGetAssetFromObject<T>(object obj, out T asset)
		{
			Concentric value;
			bool result = ObjectToAssetMap.TryGetValue(obj, out value);
			asset = ((value is T) ? ((T)(object)value) : default(T));
			return result;
		}

		public static T GetAsset<T>() where T : Concentric
		{
			return (T)GetAsset(typeof(T));
		}

		public static T GetAsset<T, T2>() where T : Concentric, T2
		{
			return GetAsset<T>();
		}

		public static Concentric GetAsset(Type assetType)
		{
			if (!Assets.ContainsKey(assetType))
			{
				throw new AssetTypeInvalidException(assetType.FullName + " is not an Asset");
			}
			return Assets[assetType];
		}

		public static Task<T2> GetObjectOrThrow<T, T1, T2>() where T : Concentric, T1
		{
			return GetObjectOrThrow<T1, T2>(GetAsset<T>());
		}

		public static async Task<T2> GetObjectOrThrow<T, T2>(Concentric concentric)
		{
			return (T2)(await GetObjectOrThrow(concentric, typeof(T)));
		}

		public static Task<object> GetObjectOrThrow<T>(Concentric concentric)
		{
			return GetObjectOrThrow(concentric, typeof(T));
		}

		public static async Task<object> GetObjectOrThrow(Concentric concentric, Type targetType)
		{
			return (await GetObjectOrNull(concentric, targetType)) ?? throw new AssetTypeInvalidException(concentric.GetType().FullName + " is not of type " + targetType.Name);
		}

		public static async Task<T2?> GetObjectOrNull<T, T1, T2>() where T : Concentric, T1
		{
			Type assetType = typeof(T);
			Concentric asset;
			return (!Assets.TryGetValue(assetType, out asset)) ? default(T2) : ((await GetObjectOrNull(asset, assetType) is T2 result) ? result : default(T2));
		}

		public static async Task<T2?> GetObjectOrNull<T, T2>(Concentric concentric)
		{
			return (await GetObjectOrNull<T>(concentric) is T2 result) ? result : default(T2);
		}

		public static Task<object?> GetObjectOrNull<T>(Concentric concentric)
		{
			return GetObjectOrNull(concentric, typeof(T));
		}

		public static Task<object?> GetObjectOrNull(Concentric concentric, Type targetType)
		{
			Type type = concentric.GetType();
			string fullName = type.FullName;
			string name = targetType.Name;
			string key = type.Assembly.FullName + "_" + fullName + "_" + name;
			if (Tasks.TryGetValue(key, out Task<object> value))
			{
				return value;
			}
			value = GetObjectOrNull_Internal(concentric, targetType);
			Tasks[key] = value;
			return value;
		}

		private static async Task<object?> GetObjectOrNull_Internal(Concentric concentric, Type targetType)
		{
			Type assetType = concentric.GetType();
			string name = assetType.FullName;
			string targetTypeName = targetType.Name;
			string key = assetType.Assembly.FullName + "_" + name + "_" + targetTypeName;
			if (Objects.TryGetValue(key, out object result))
			{
				return result;
			}
			object returnedObject;
			switch (targetTypeName)
			{
			case "ISkill":
			{
				Task<SkillDef> skillTask = (concentric as ISkill)?.BuildObject();
				if (skillTask == null)
				{
					return null;
				}
				SkillDef skill = await skillTask;
				IEnumerable<Type> entityStates = ((ISkill)concentric).GetEntityStates();
				Objects[key + "_EntityStates"] = entityStates;
				skill.skillName = name + "SkillDef";
				skill.activationState = new SerializableEntityStateType(entityStates.FirstOrDefault());
				returnedObject = skill;
				break;
			}
			case "IEffect":
			{
				Task<GameObject> effectTask = (concentric as IEffect)?.BuildObject();
				if (effectTask == null)
				{
					return null;
				}
				GameObject effect = await effectTask;
				if (!Object.op_Implicit((Object)(object)effect.GetComponent<VFXAttributes>()))
				{
					VFXAttributes attributes = effect.AddComponent<VFXAttributes>();
					attributes.vfxPriority = (VFXPriority)2;
					attributes.DoNotPool = true;
				}
				if (!Object.op_Implicit((Object)(object)effect.GetComponent<EffectComponent>()))
				{
					EffectComponent comp = effect.AddComponent<EffectComponent>();
					comp.applyScale = false;
					comp.parentToReferencedTransform = true;
					comp.positionAtReferencedTransform = true;
				}
				returnedObject = effect;
				break;
			}
			case "IVariant":
			{
				Task<Variant> variantTask = (concentric as IVariant)?.BuildObject();
				Variant variant;
				if (variantTask == null)
				{
					SkillDef skillDef = await GetObjectOrNull<ISkill, SkillDef>(concentric);
					if (skillDef == null)
					{
						return null;
					}
					Variant val2 = new Variant
					{
						skillDef = skillDef
					};
					((Variant)(ref val2)).viewableNode = new Node(skillDef.skillName, false, (Node)null);
					variant = val2;
				}
				else
				{
					variant = await variantTask;
				}
				returnedObject = variant;
				break;
			}
			case "ISkillFamily":
			{
				if (!(concentric is ISkillFamily familyAsset))
				{
					return null;
				}
				SkillFamily family = await familyAsset.BuildObject();
				if (family == null)
				{
					family = ScriptableObject.CreateInstance<SkillFamily>();
					SkillFamily val = family;
					val.variants = await Task.WhenAll(familyAsset.GetSkillAssets().Select(GetObjectOrThrow<IVariant, Variant>));
				}
				returnedObject = family;
				break;
			}
			case "IModel":
			{
				if (!(concentric is IModel modelAsset))
				{
					return null;
				}
				returnedObject = await modelAsset.BuildObject();
				Objects[key] = returnedObject;
				ObjectToAssetMap[returnedObject] = concentric;
				ModelSkinController skinController = ExtensionMethods.GetOrAddComponent<ModelSkinController>((GameObject)returnedObject);
				Task.WhenAll(modelAsset.GetSkins().Select(GetObjectOrThrow<ISkin, SkinDef>)).ContinueWith(delegate(Task<SkinDef[]> completedTask)
				{
					skinController.skins = completedTask.Result;
				}).ConfigureAwait(continueOnCapturedContext: false);
				break;
			}
			default:
			{
				object obj = targetType.GetMethod("BuildObject")?.Invoke(concentric, null);
				if (!(obj is Task task))
				{
					return null;
				}
				await task;
				PropertyInfo taskType = task.GetType().GetProperty("Result");
				if (taskType == null)
				{
					return null;
				}
				returnedObject = taskType.GetValue(task);
				break;
			}
			}
			Type returnedType = returnedObject.GetType();
			Type scriptableObject = typeof(ScriptableObject);
			PropertyInfo cachedName = returnedType.GetProperty("cachedName");
			MethodInfo nameProperty = scriptableObject.GetProperty("name").GetSetMethod();
			string objectName = (assetType.Name + "_" + targetTypeName).Replace(".", "_");
			cachedName?.GetSetMethod().Invoke(returnedObject, new object[1] { objectName });
			if ((object)cachedName == null && scriptableObject.IsAssignableFrom(returnedType))
			{
				nameProperty.Invoke(returnedObject, new object[1] { objectName });
			}
			if ("IModel" != targetTypeName && Objects.TryGetValue(key, out object existingObject))
			{
				ConcentricContentPlugin.LOG.LogWarning((object)("You shouldn't be seeing this(" + key + "). It might mean a race condition, report to Concentric Content author."));
				return existingObject;
			}
			Objects[key] = returnedObject;
			ObjectToAssetMap[returnedObject] = concentric;
			return returnedObject;
		}

		public virtual Task Initialize()
		{
			return Task.CompletedTask;
		}
	}
	public static class AssetExtensionMethods
	{
		public static Task<ItemDef> GetItemDef<T>(this T _) where T : Concentric, IItem
		{
			return Concentric.GetItemDef<T>();
		}

		public static Task<ItemIndex> GetItemIndex<T>(this T _) where T : Concentric, IItem
		{
			return Concentric.GetItemIndex<T>();
		}

		public static Task<UnlockableDef> GetUnlockableDef<T>(this T _) where T : Concentric, IUnlockable
		{
			return Concentric.GetUnlockableDef<T>();
		}

		public static Task<BuffDef> GetBuffDef<T>(this T _) where T : Concentric, IBuff
		{
			return Concentric.GetBuffDef<T>();
		}

		public static Task<BuffIndex> GetBuffIndex<T>(this T _) where T : Concentric, IBuff
		{
			return Concentric.GetBuffIndex<T>();
		}

		public static Task<BodyIndex> GetBodyIndex<T>(this T _) where T : Concentric, IBody
		{
			return Concentric.GetBodyIndex<T>();
		}

		public static Task<Material> GetMaterial<T>(this T _) where T : Concentric, IMaterial
		{
			return Concentric.GetMaterial<T>();
		}

		public static Task<SurvivorDef> GetSurvivorDef<T>(this T _) where T : Concentric, ISurvivor
		{
			return Concentric.GetSurvivorDef<T>();
		}

		public static Task<SkinDef> GetSkinDef<T>(this T _) where T : Concentric, ISkin
		{
			return Concentric.GetSkinDef<T>();
		}

		public static Task<SkillDef> GetSkillDef<T>(this T _) where T : Concentric, ISkill
		{
			return Concentric.GetSkillDef<T>();
		}

		public static Task<MusicTrackDef> GetMusicTrackDef<T>(this T _) where T : Concentric, IMusicTrack
		{
			return Concentric.GetMusicTrackDef<T>();
		}

		public static Task<SkillFamily> GetSkillFamily<T>(this T _) where T : Concentric, ISkillFamily
		{
			return Concentric.GetSkillFamily<T>();
		}

		public static Task<Variant> GetSkillFamilyVariant<T>(this T _) where T : Concentric, ISkill
		{
			return Concentric.GetSkillFamilyVariant<T>();
		}

		public static Task<GameObject> GetNetworkedObject<T>(this T _) where T : Concentric, INetworkedObject
		{
			return Concentric.GetNetworkedObject<T>();
		}

		public static Task<GameObject> GetGenericObject<T>(this T _) where T : Concentric, IGenericObject
		{
			return Concentric.GetGenericObject<T>();
		}

		public static Task<GameObject> GetProjectile<T>(this T _) where T : Concentric, IProjectile
		{
			return Concentric.GetProjectile<T>();
		}

		public static Task<GameObject> GetProjectileGhost<T>(this T _) where T : Concentric, IProjectileGhost
		{
			return Concentric.GetProjectileGhost<T>();
		}

		public static Task<GameObject> GetEffect<T>(this T _) where T : Concentric, IEffect
		{
			return Concentric.GetEffect<T>();
		}

		public static Task<GameObject> GetMaster<T>(this T _) where T : Concentric, IMaster
		{
			return Concentric.GetMaster<T>();
		}

		public static Task<GameObject> GetBody<T>(this T _) where T : Concentric, IBody
		{
			return Concentric.GetBody<T>();
		}

		public static Task<GameObject> GetBodyDisplay<T>(this T _) where T : Concentric, IBodyDisplay
		{
			return Concentric.GetBodyDisplay<T>();
		}

		public static Task<GameObject> GetModel<T>(this T _) where T : Concentric, IModel
		{
			return Concentric.GetModel<T>();
		}
	}
	public class AssetTypeInvalidException : Exception
	{
		public AssetTypeInvalidException(string message)
			: base(message)
		{
		}
	}
	[BepInPlugin("bubbet.concentriccontent", "ConcentricContent", "1.0.0")]
	public class ConcentricContentPlugin : BaseUnityPlugin
	{
		public static Harmony Harm;

		public static ConcentricContentPlugin Instance;

		public static ManualLogSource LOG;

		public const string Guid = "bubbet.concentriccontent";

		public void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Instance = this;
			LOG = ((BaseUnityPlugin)this).Logger;
			Harm = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
			Harm.PatchAll();
		}
	}
	public static class ExtensionMethods
	{
		public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
		{
			T val = gameObject.GetComponent<T>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = gameObject.AddComponent<T>();
			}
			return val;
		}

		public static TV GetOrSet<TK, TV>(this Dictionary<TK, TV> dict, TK key, Func<TV> valueGetter)
		{
			if (dict.TryGetValue(key, out TV value))
			{
				return value;
			}
			return dict[key] = valueGetter();
		}
	}
	[HarmonyPatch]
	public static class ExtraHealthBarSegments
	{
		[RequireComponent(typeof(HealthBar))]
		public class ExtraHealthBarInfoTracker : MonoBehaviour
		{
			public List<BarData> BarInfos = null;

			private HealthBar? _healthBar;

			private Material? _defaultMaterial;

			public HealthBar HealthBar
			{
				get
				{
					if ((Object)(object)_healthBar == (Object)null || !Object.op_Implicit((Object)(object)_healthBar))
					{
						_healthBar = ((Component)this).GetComponent<HealthBar>();
					}
					return _healthBar;
				}
			}

			private Material DefaultMaterial
			{
				get
				{
					if ((Object)(object)_defaultMaterial == (Object)null || !Object.op_Implicit((Object)(object)_defaultMaterial))
					{
						_defaultMaterial = ((Graphic)HealthBar.barAllocator.elementPrefab.GetComponent<Image>()).material;
					}
					return _defaultMaterial;
				}
			}

			public void CheckInventory(Inventory inv, CharacterBody characterBody, HealthComponent healthComponent)
			{
				foreach (BarData barInfo in BarInfos)
				{
					barInfo.CheckInventory(ref barInfo.Info, inv, characterBody, healthComponent);
				}
			}

			public HealthBarValues UpdateInfo(ref HealthBarValues barValues)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)HealthBar.source))
				{
					return barValues;
				}
				foreach (BarData barInfo in BarInfos)
				{
					barInfo.UpdateInfo(ref barInfo.Info, ref barValues);
				}
				return barValues;
			}

			public void ApplyBar(ref int i)
			{
				foreach (Image element in HealthBar.barAllocator.elements)
				{
					if ((Object)(object)((Graphic)element).material != (Object)(object)DefaultMaterial)
					{
						((Graphic)element).material = DefaultMaterial;
					}
				}
				foreach (BarData barInfo in BarInfos)
				{
					if (barInfo.Info.enabled)
					{
						Image image = HealthBar.barAllocator.elements[i];
						barInfo.ApplyBar(ref barInfo.Info, image, ref i);
					}
				}
			}

			public void Awake()
			{
				BarInfos = _barDataTypes.Select((Type dataType) => ((BarData)Activator.CreateInstance(dataType)).Init(this)).ToList();
			}
		}

		internal static List<Type> _barDataTypes = new List<Type>();

		public static void AddType<T>() where T : BarData, new()
		{
			_barDataTypes.Add(typeof(T));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HealthBar), "Awake")]
		public static void AddTracker(HealthBar __instance)
		{
			((Component)__instance).gameObject.AddComponent<ExtraHealthBarInfoTracker>();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HealthBar), "CheckInventory")]
		public static void CheckInventory(HealthBar __instance)
		{
			ExtraHealthBarInfoTracker component = ((Component)__instance).GetComponent<ExtraHealthBarInfoTracker>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			HealthComponent source = __instance.source;
			if (!Object.op_Implicit((Object)(object)source))
			{
				return;
			}
			CharacterBody body = source.body;
			if (Object.op_Implicit((Object)(object)body))
			{
				Inventory inventory = body.inventory;
				if (Object.op_Implicit((Object)(object)inventory))
				{
					component.CheckInventory(inventory, body, source);
				}
			}
		}

		[HarmonyILManipulator]
		[HarmonyPatch(typeof(HealthBar), "UpdateBarInfos")]
		public static void UpdateInfos(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			val.GotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<HealthComponent>(x, "GetHealthBarValues")
			});
			val.Emit(OpCodes.Ldarg_0);
			val.EmitDelegate<Func<HealthBarValues, HealthBar, HealthBarValues>>((Func<HealthBarValues, HealthBar, HealthBarValues>)delegate(HealthBarValues values, HealthBar bar)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				ExtraHealthBarInfoTracker component = ((Component)bar).GetComponent<ExtraHealthBarInfoTracker>();
				return component.UpdateInfo(ref values);
			});
		}

		[HarmonyILManipulator]
		[HarmonyPatch(typeof(HealthBar), "ApplyBars")]
		public static void ApplyBar(ILContext il)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			int cls = -1;
			FieldReference fld = null;
			val.GotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloca(x, ref cls),
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchStfld(x, ref fld)
			});
			val.GotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<BarInfoCollection>(x, "GetActiveCount")
			});
			val.Emit(OpCodes.Ldarg_0);
			val.EmitDelegate<Func<int, HealthBar, int>>((Func<int, HealthBar, int>)delegate(int i, HealthBar bar)
			{
				ExtraHealthBarInfoTracker component2 = ((Component)bar).GetComponent<ExtraHealthBarInfoTracker>();
				i += component2.BarInfos.Count((BarData x) => x.Info.enabled);
				return i;
			});
			val.Index = il.Instrs.Count - 2;
			val.Emit(OpCodes.Ldloca, cls);
			val.Emit(OpCodes.Ldarg_0);
			val.Emit(OpCodes.Ldloca, cls);
			val.Emit(OpCodes.Ldfld, fld);
			val.EmitDelegate<Func<HealthBar, int, int>>((Func<HealthBar, int, int>)delegate(HealthBar bar, int i)
			{
				ExtraHealthBarInfoTracker component = ((Component)bar).GetComponent<ExtraHealthBarInfoTracker>();
				component.ApplyBar(ref i);
				return i;
			});
			val.Emit(OpCodes.Stfld, fld);
		}
	}
	public abstract class BarData
	{
		public ExtraHealthBarSegments.ExtraHealthBarInfoTracker Tracker = null;

		public BarInfo Info;

		public BarStyle? CachedStyle;

		public abstract BarStyle GetStyle();

		public virtual void UpdateInfo(ref BarInfo inf, ref HealthBarValues healthBarValues)
		{
			//IL_0007: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_005e: 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_0070: 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)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			BarStyle valueOrDefault = CachedStyle.GetValueOrDefault();
			if (!CachedStyle.HasValue)
			{
				valueOrDefault = GetStyle();
				CachedStyle = valueOrDefault;
			}
			BarStyle value = CachedStyle.Value;
			inf.enabled &= value.enabled;
			inf.color = value.baseColor;
			inf.imageType = value.imageType;
			inf.sprite = value.sprite;
			inf.sizeDelta = value.sizeDelta;
		}

		public virtual void CheckInventory(ref BarInfo inf, Inventory inventory, CharacterBody characterBody, HealthComponent healthComponent)
		{
		}

		public virtual void ApplyBar(ref BarInfo inf, Image image, ref int i)
		{
			//IL_0003: 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)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			image.type = inf.imageType;
			image.sprite = inf.sprite;
			((Graphic)image).color = inf.color;
			RectTransform val = (RectTransform)((Component)image).transform;
			val.anchorMin = new Vector2(inf.normalizedXMin, 0f);
			val.anchorMax = new Vector2(inf.normalizedXMax, 1f);
			val.anchoredPosition = Vector2.zero;
			val.sizeDelta = new Vector2(inf.sizeDelta * 0.5f + 1f, inf.sizeDelta + 1f);
			i++;
		}

		public virtual BarData Init(ExtraHealthBarSegments.ExtraHealthBarInfoTracker extraHealthBarInfoTracker)
		{
			Tracker = extraHealthBarInfoTracker;
			return this;
		}
	}
	[HarmonyPatch]
	public class HarmonyPatches
	{
		[HarmonyILManipulator]
		[HarmonyPatch(typeof(Row), "FromSkillSlot")]
		public static void FromSkillSlot(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			val.GotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchNewobj<Row>(x)
			});
			val.Emit(OpCodes.Ldarg_3);
			val.EmitDelegate<Func<string, GenericSkill, string>>((Func<string, GenericSkill, string>)delegate(string s, GenericSkill skill)
			{
				if (!Concentric.TryGetAssetFromObject<ISkillFamily>(skill.skillFamily, out var asset))
				{
					return s;
				}
				string nameToken = asset.GetNameToken(skill);
				return Utility.IsNullOrWhiteSpace(nameToken) ? s : nameToken;
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(CharacterModel), "UpdateOverlayStates")]
		private static void CharacterModelUpdateOverlayStates(CharacterModel __instance, ref bool __result)
		{
			__result |= ((Component)__instance).gameObject.GetOrAddComponent<ExtraOverlayTracker>().UpdateRequired(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(CharacterModel), "UpdateOverlays")]
		private static void CharacterModelUpdateOverlays(CharacterModel __instance)
		{
			CharacterModel __instance2 = __instance;
			foreach (IOverlay item in Concentric.Overlays.Where((IOverlay overlay) => overlay.CheckEnabled(__instance2) && __instance2.activeOverlayCount < CharacterModel.maxOverlays))
			{
				Material[] currentOverlays = __instance2.currentOverlays;
				CharacterModel obj = __instance2;
				int activeOverlayCount = obj.activeOverlayCount;
				obj.activeOverlayCount = activeOverlayCount + 1;
				currentOverlays[activeOverlayCount] = Concentric.OverlayMaterials[item];
			}
		}

		[HarmonyILManipulator]
		[HarmonyPatch(typeof(CharacterModel), "UpdateMaterials")]
		public static void InjectMaterial(ILContext il)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CharacterModel>(x, "UpdateRendererMaterials")
			}))
			{
				ConcentricContentPlugin.LOG.LogError((object)"Failed to match il in character model inject material.");
				return;
			}
			int index = val.Index;
			int iIndex = -1;
			if (!val.TryGotoPrev(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref iIndex)
			}))
			{
				return;
			}
			val.Index = index;
			val.Emit(OpCodes.Ldarg_0);
			val.Emit(OpCodes.Ldloc, iIndex);
			val.EmitDelegate<Action<CharacterModel, int>>((Action<CharacterModel, int>)delegate(CharacterModel characterModel, int i)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				CharacterModel characterModel2 = characterModel;
				RendererInfo baseRenderer = characterModel2.baseRendererInfos[i];
				IMaterialSwap materialSwap = (from overlay in Concentric.MaterialSwaps
					where overlay.CheckEnabled(characterModel2, baseRenderer)
					select overlay into x
					orderby x.Priority
					select x).FirstOrDefault();
				if (materialSwap != null)
				{
					characterModel2.baseRendererInfos[i].renderer.material = Concentric.MaterialSwapMaterials[materialSwap];
				}
			});
		}

		[HarmonyILManipulator]
		[HarmonyPatch(typeof(LoadoutPanelController), "Rebuild")]
		public static void FixLoadOutPanelControllerShowingHiddenSkillsInLoadOutTab(ILContext il)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			ILLabel brTarget = null;
			int num5 = default(int);
			int num4 = default(int);
			MethodReference val3 = default(MethodReference);
			int num3 = default(int);
			if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[5]
			{
				(Instruction x) => ILPatternMatchingExt.MatchBr(x, ref brTarget),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num5),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num4),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, ref val3),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref num3)
			}))
			{
				ConcentricContentPlugin.LOG.LogError((object)"Failed to match il in load out panel hidden skills fix.");
				return;
			}
			int index = val.Index;
			val.Index = index - 1;
			val.Emit(OpCodes.Dup);
			index = val.Index;
			val.Index = index + 1;
			val.Emit(OpCodes.Ldfld, typeof(GenericSkill).GetField("hideInCharacterSelect"));
			ILLabel val2 = val.DefineLabel();
			val.Emit(OpCodes.Brtrue, (object)val2);
			val.Goto(brTarget.Target, (MoveType)0, false);
			int num2 = default(int);
			int num = default(int);
			val.GotoPrev(new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num2),
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 1),
				(Instruction x) => ILPatternMatchingExt.MatchAdd(x),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref num)
			});
			val.MarkLabel(val2);
		}
	}
	public class ExtraOverlayTracker : MonoBehaviour
	{
		private readonly Dictionary<IOverlay, bool> wasEnabled = new Dictionary<IOverlay, bool>();

		public bool UpdateRequired(CharacterModel model)
		{
			bool result = false;
			foreach (IOverlay overlay in Concentric.Overlays)
			{
				bool flag = overlay.CheckEnabled(model);
				if (!wasEnabled.TryGetValue(overlay, out var value) || flag != value)
				{
					wasEnabled[overlay] = flag;
					result = true;
				}
			}
			return result;
		}
	}
	public interface IGameObject
	{
	}
	public interface IGenericObject : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface INetworkedObject : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface IProjectile : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface IProjectileGhost : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface IEffect : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface IMaster : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface IBody : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface IBodyDisplay : IGameObject
	{
		Task<GameObject> BuildObject();
	}
	public interface IModel : IGameObject
	{
		Task<GameObject> BuildObject();

		IEnumerable<Concentric> GetSkins();
	}
	public interface ISurvivor
	{
		Task<SurvivorDef> BuildObject();
	}
	public interface ISkin
	{
		Task<SkinDef> BuildObject();

		static void AddDefaults(ref SkinDef skinDef)
		{
			SkinDef val = skinDef;
			if (val.baseSkins == null)
			{
				val.baseSkins = Array.Empty<SkinDef>();
			}
			val = skinDef;
			if (val.gameObjectActivations == null)
			{
				val.gameObjectActivations = Array.Empty<GameObjectActivation>();
			}
			val = skinDef;
			if (val.meshReplacements == null)
			{
				val.meshReplacements = Array.Empty<MeshReplacement>();
			}
			val = skinDef;
			if (val.minionSkinReplacements == null)
			{
				val.minionSkinReplacements = Array.Empty<MinionSkinReplacement>();
			}
			val = skinDef;
			if (val.projectileGhostReplacements == null)
			{
				val.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
			}
		}
	}
	public interface IItem
	{
		Task<ItemDef> BuildObject();
	}
	public interface IMaterial
	{
		Task<Material> BuildObject();
	}
	public interface IOverlay
	{
		Task<Material> BuildObject();

		bool CheckEnabled(CharacterModel model);
	}
	public interface IMaterialSwap
	{
		int Priority { get; }

		Task<Material> BuildObject();

		bool CheckEnabled(CharacterModel model, RendererInfo targetRendererInfo);
	}
	public interface IUnlockable
	{
		Task<UnlockableDef> BuildObject();
	}
	public interface IMusicTrack
	{
		Task<MusicTrackDef> BuildObject();
	}
	public interface IBuff
	{
		Task<BuffDef> BuildObject();
	}
	public interface ISkillFamily
	{
		Task<SkillFamily> BuildObject()
		{
			return Task.FromResult<SkillFamily>(null);
		}

		IEnumerable<Concentric> GetSkillAssets();

		string GetNameToken(GenericSkill skill)
		{
			return "";
		}
	}
	public interface ISkill
	{
		Task<SkillDef> BuildObject();

		IEnumerable<Type> GetEntityStates();
	}
	public interface IEntityStates
	{
		IEnumerable<Type> GetEntityStates();
	}
	public interface IVariant
	{
		Task<Variant> BuildObject();
	}
}