Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of ConcentricContent v1.0.2
plugins/ConcentricContent/ConcentricContent.dll
Decompiled 11 months agousing 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.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("ConcentricContent")] [assembly: AssemblyConfiguration("Release")] [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 item in types.Where((Type x) => typeof(BarData).IsAssignableFrom(x) && !x.IsAbstract)) { ExtraHealthBarSegments._barDataTypes.Add(item); } Dictionary<Type, Concentric> dictionary = types.Where((Type x) => typeof(Concentric).IsAssignableFrom(x) && !x.IsAbstract).ToDictionary((Type x) => x, (Type x) => (Concentric)Activator.CreateInstance(x)); foreach (var (key, value) in dictionary) { Assets[key] = value; } Concentric[] instances = dictionary.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[] array = await Task.WhenAll(overlays.Select((IOverlay x) => GetObjectOrThrow<IOverlay, Material>((Concentric)x))); for (int i = 0; i < overlays.Length; i++) { OverlayMaterials[overlays[i]] = array[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[] array2 = await Task.WhenAll(swaps.Select((IMaterialSwap x) => GetObjectOrThrow<IMaterialSwap, Material>((Concentric)x))); for (int j = 0; j < overlays.Length; j++) { MaterialSwapMaterials[swaps[j]] = array2[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>))); networkedObjectPrefabs = result.bodyPrefabs; networkedObjectPrefabs.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>))); networkedObjectPrefabs = result.projectilePrefabs; networkedObjectPrefabs.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()); networkedObjectPrefabs = result.masterPrefabs; networkedObjectPrefabs.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 typeFromHandle = typeof(T); Concentric value; return (!Assets.TryGetValue(typeFromHandle, out value)) ? default(T2) : ((await GetObjectOrNull(value, typeFromHandle) is T2 val) ? val : default(T2)); } public static async Task<T2?> GetObjectOrNull<T, T2>(Concentric concentric) { return (await GetObjectOrNull<T>(concentric) is T2 val) ? val : 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 value)) { return value; } object obj2; switch (targetTypeName) { case "ISkill": { Task<SkillDef> task2 = (concentric as ISkill)?.BuildObject(); if (task2 == null) { return null; } SkillDef obj3 = await task2; IEnumerable<Type> entityStates = ((ISkill)concentric).GetEntityStates(); Objects[key + "_EntityStates"] = entityStates; obj3.skillName = name + "SkillDef"; obj3.activationState = new SerializableEntityStateType(entityStates.FirstOrDefault()); obj2 = obj3; break; } case "IEffect": { Task<GameObject> task4 = (concentric as IEffect)?.BuildObject(); if (task4 == null) { return null; } GameObject val5 = await task4; if (!Object.op_Implicit((Object)(object)val5.GetComponent<VFXAttributes>())) { VFXAttributes obj4 = val5.AddComponent<VFXAttributes>(); obj4.vfxPriority = (VFXPriority)2; obj4.DoNotPool = true; } if (!Object.op_Implicit((Object)(object)val5.GetComponent<EffectComponent>())) { EffectComponent obj5 = val5.AddComponent<EffectComponent>(); obj5.applyScale = false; obj5.parentToReferencedTransform = true; obj5.positionAtReferencedTransform = true; } obj2 = val5; break; } case "IVariant": { Task<Variant> task3 = (concentric as IVariant)?.BuildObject(); Variant val4; if (task3 == null) { SkillDef val2 = await GetObjectOrNull<ISkill, SkillDef>(concentric); if (val2 == null) { return null; } Variant val3 = default(Variant); val3.skillDef = val2; ((Variant)(ref val3)).viewableNode = new Node(val2.skillName, false, (Node)null); val4 = val3; } else { val4 = await task3; } obj2 = val4; 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>)); } obj2 = family; break; } case "IModel": { if (!(concentric is IModel modelAsset)) { return null; } obj2 = await modelAsset.BuildObject(); Objects[key] = obj2; ObjectToAssetMap[obj2] = concentric; ModelSkinController skinController = ExtensionMethods.GetOrAddComponent<ModelSkinController>((GameObject)obj2); 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 property = task.GetType().GetProperty("Result"); if (property == null) { return null; } obj2 = property.GetValue(task); break; } } Type type = obj2.GetType(); Type typeFromHandle = typeof(ScriptableObject); PropertyInfo property2 = type.GetProperty("cachedName"); MethodInfo setMethod = typeFromHandle.GetProperty("name").GetSetMethod(); string text = (assetType.Name + "_" + targetTypeName).Replace(".", "_"); property2?.GetSetMethod().Invoke(obj2, new object[1] { text }); if ((object)property2 == null && typeFromHandle.IsAssignableFrom(type)) { setMethod.Invoke(obj2, new object[1] { text }); } if ("IModel" != targetTypeName && Objects.TryGetValue(key, out object value2)) { ConcentricContentPlugin.LOG.LogWarning((object)("You shouldn't be seeing this(" + key + "). It might mean a race condition, report to Concentric Content author.")); return value2; } Objects[key] = obj2; ObjectToAssetMap[obj2] = concentric; return obj2; } 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.2.4")] public class ConcentricContentPlugin : BaseUnityPlugin { public static Harmony Harm; public static ConcentricContentPlugin Instance; public static ManualLogSource LOG; public const string Guid = "bubbet.concentriccontent"; public const string Version = "1.0.2.4"; public void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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; 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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((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>)((HealthBarValues values, HealthBar bar) => ((Component)bar).GetComponent<ExtraHealthBarInfoTracker>().UpdateInfo(ref values))); } [HarmonyILManipulator] [HarmonyPatch(typeof(HealthBar), "ApplyBars")] public static void ApplyBar(ILContext il) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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 component = ((Component)bar).GetComponent<ExtraHealthBarInfoTracker>(); i += component.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) { ((Component)bar).GetComponent<ExtraHealthBarInfoTracker>().ApplyBar(ref i); return i; }); val.Emit(OpCodes.Stfld, fld); } } public abstract class BarData { public ExtraHealthBarSegments.ExtraHealthBarInfoTracker Tracker; public BarInfo Info; public BarStyle? CachedStyle; public abstract BarStyle GetStyle(); public virtual void UpdateInfo(ref BarInfo inf, ref HealthBarValues healthBarValues) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_005b: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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) 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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0037: 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)) ? nameToken : s; }); } [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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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.EmitDelegate<Func<GenericSkill, bool>>((Func<GenericSkill, bool>)((GenericSkill skill) => Concentric.TryGetAssetFromObject<ISkillFamily>(skill.skillFamily, out var asset) && asset.HiddenFromCharacterSelect)); 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 { bool HiddenFromCharacterSelect => false; 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(); } }