Decompiled source of InheritanceDataBlocks v1.1.5

InheritanceDataBlocks.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using GameData;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppJsonNet.Linq;
using Il2CppSystem;
using Il2CppSystem.Linq;
using InheritanceDataBlocks.API;
using InheritanceDataBlocks.Inheritance;
using InheritanceDataBlocks.Utils;
using InjectLib.JsonNETInjection;
using InjectLib.JsonNETInjection.Handler;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("InheritanceDataBlocks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+02f0cb61aaa35a3e8ed810578ef8ee09f430b392")]
[assembly: AssemblyProduct("InheritanceDataBlocks")]
[assembly: AssemblyTitle("InheritanceDataBlocks")]
[assembly: TargetPlatform("Windows7.0")]
[assembly: SupportedOSPlatform("Windows7.0")]
[assembly: AssemblyVersion("1.0.0.0")]
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 InheritanceDataBlocks
{
	internal static class Configuration
	{
		public static bool DebugChains { get; private set; }

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			BindAll(new ConfigFile(Path.Combine(Paths.ConfigPath, "InheritanceDataBlocks.cfg"), true));
		}

		private static void BindAll(ConfigFile config)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0030: Expected O, but got Unknown
			string text = "General Settings";
			string text2 = "Enable Debug Logging";
			string text3 = "Prints inheritance chains to the console when data blocks are loaded (useful when debugging broken child blocks).";
			DebugChains = config.Bind<bool>(new ConfigDefinition(text, text2), DebugChains, new ConfigDescription(text3, (AcceptableValueBase)null, Array.Empty<object>())).Value;
		}
	}
	internal sealed class DataBlockHandler<T> : Il2CppJsonReferenceTypeHandler<T> where T : GameDataBlockBase<T>
	{
		public override void OnRead(in Object result, in JToken jToken)
		{
			JObject val = ((Il2CppObjectBase)jToken).TryCast<JObject>();
			JToken val2 = default(JToken);
			if (!val.TryGetValue("parentID", ref val2))
			{
				return;
			}
			Type typeFromHandle = typeof(T);
			List<PropertyInfo> list = new List<PropertyInfo>(((JContainer)val).Count - 1);
			JProperty[] array = Il2CppArrayBase<JProperty>.op_Implicit(Enumerable.ToArray<JProperty>(val.Properties()));
			foreach (JProperty val3 in array)
			{
				if (!(val3.Name == "parentID"))
				{
					PropertyInfo propertyInfo = InheritanceAPI<T>.CacheProperty(typeFromHandle, val3.Name);
					if (propertyInfo != null)
					{
						list.Add(propertyInfo);
					}
				}
			}
			InheritanceAPI<T>.AddDataBlock(((Il2CppObjectBase)result).TryCast<T>(), list, (uint)val2);
		}
	}
	internal static class DataBlockHandlerManager
	{
		internal static void AddHandler<T>() where T : GameDataBlockBase<T>
		{
			JsonInjector.AddHandler<T>((Il2CppJsonReferenceTypeHandler<T>)new DataBlockHandler<T>());
		}

		internal static void Init()
		{
			DataBlockHandlerManager.AddHandler<ArchetypeDataBlock>();
			DataBlockHandlerManager.AddHandler<ArtifactDataBlock>();
			DataBlockHandlerManager.AddHandler<ArtifactDistributionDataBlock>();
			DataBlockHandlerManager.AddHandler<ArtifactTagDataBlock>();
			DataBlockHandlerManager.AddHandler<AtmosphereDataBlock>();
			DataBlockHandlerManager.AddHandler<BigPickupDistributionDataBlock>();
			DataBlockHandlerManager.AddHandler<BoosterImplantConditionDataBlock>();
			DataBlockHandlerManager.AddHandler<BoosterImplantEffectDataBlock>();
			DataBlockHandlerManager.AddHandler<BoosterImplantTemplateDataBlock>();
			DataBlockHandlerManager.AddHandler<ChainedPuzzleDataBlock>();
			DataBlockHandlerManager.AddHandler<ChainedPuzzleTypeDataBlock>();
			DataBlockHandlerManager.AddHandler<CloudsDataBlock>();
			DataBlockHandlerManager.AddHandler<CommodityDataBlock>();
			DataBlockHandlerManager.AddHandler<ComplexResourceSetDataBlock>();
			DataBlockHandlerManager.AddHandler<ConsumableDistributionDataBlock>();
			DataBlockHandlerManager.AddHandler<CustomAssetShardDataBlock>();
			DataBlockHandlerManager.AddHandler<DimensionDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemyBalancingDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemyBehaviorDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemyDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemyDetectionDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemyGroupDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemyMovementDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemyPopulationDataBlock>();
			DataBlockHandlerManager.AddHandler<EnemySFXDataBlock>();
			DataBlockHandlerManager.AddHandler<EnvironmentFeedbackDataBlock>();
			DataBlockHandlerManager.AddHandler<EventSequenceActionDataBlock>();
			DataBlockHandlerManager.AddHandler<EventSequenceDataBlock>();
			DataBlockHandlerManager.AddHandler<ExpeditionBalanceDataBlock>();
			DataBlockHandlerManager.AddHandler<ExtractionEventDataBlock>();
			DataBlockHandlerManager.AddHandler<FeedbackDataBlock>();
			DataBlockHandlerManager.AddHandler<FlashlightSettingsDataBlock>();
			DataBlockHandlerManager.AddHandler<FogScenarioDataBlock>();
			DataBlockHandlerManager.AddHandler<FogSettingsDataBlock>();
			DataBlockHandlerManager.AddHandler<GameSetupDataBlock>();
			DataBlockHandlerManager.AddHandler<GearCategoryDataBlock>();
			DataBlockHandlerManager.AddHandler<GearCategoryFilterDataBlock>();
			DataBlockHandlerManager.AddHandler<GearDataBlock>();
			DataBlockHandlerManager.AddHandler<GearDecalDataBlock>();
			DataBlockHandlerManager.AddHandler<GearFlashlightPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearFrontPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearMagPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearMeleeHandlePartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearMeleeHeadPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearMeleeNeckPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearMeleePommelPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearPaletteDataBlock>();
			DataBlockHandlerManager.AddHandler<GearPartAttachmentDataBlock>();
			DataBlockHandlerManager.AddHandler<GearPatternDataBlock>();
			DataBlockHandlerManager.AddHandler<GearPerkDataBlock>();
			DataBlockHandlerManager.AddHandler<GearReceiverPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearSightPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearStockPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearToolDeliveryPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearToolGripPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearToolMainPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearToolPayloadPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearToolScreenPartDataBlock>();
			DataBlockHandlerManager.AddHandler<GearToolTargetingPartDataBlock>();
			DataBlockHandlerManager.AddHandler<ItemDataBlock>();
			DataBlockHandlerManager.AddHandler<ItemFPSSettingsDataBlock>();
			DataBlockHandlerManager.AddHandler<ItemMovementAnimationDataBlock>();
			DataBlockHandlerManager.AddHandler<ItemPartDataBlock>();
			DataBlockHandlerManager.AddHandler<LevelGenSettingsDataBlock>();
			DataBlockHandlerManager.AddHandler<LevelLayoutDataBlock>();
			DataBlockHandlerManager.AddHandler<LightSettingsDataBlock>();
			DataBlockHandlerManager.AddHandler<LootDataBlock>();
			DataBlockHandlerManager.AddHandler<MarkerGroupDataBlock>();
			DataBlockHandlerManager.AddHandler<MeleeAnimationSetDataBlock>();
			DataBlockHandlerManager.AddHandler<MeleeArchetypeDataBlock>();
			DataBlockHandlerManager.AddHandler<MeleeSFXDataBlock>();
			DataBlockHandlerManager.AddHandler<MiningMarkerDataBlock>();
			DataBlockHandlerManager.AddHandler<MLSArrayDescriptorReferenceDataBlock>();
			DataBlockHandlerManager.AddHandler<MusicStateDataBlock>();
			DataBlockHandlerManager.AddHandler<PlayerDataBlock>();
			DataBlockHandlerManager.AddHandler<PlayerDialogDataBlock>();
			DataBlockHandlerManager.AddHandler<PlayerOfflineGearDataBlock>();
			DataBlockHandlerManager.AddHandler<RecoilDataBlock>();
			DataBlockHandlerManager.AddHandler<RundownDataBlock>();
			DataBlockHandlerManager.AddHandler<ServiceMarkerDataBlock>();
			DataBlockHandlerManager.AddHandler<StaticSpawnDataBlock>();
			DataBlockHandlerManager.AddHandler<SurvivalWavePopulationDataBlock>();
			DataBlockHandlerManager.AddHandler<SurvivalWaveSettingsDataBlock>();
			DataBlockHandlerManager.AddHandler<TechMarkerDataBlock>();
			DataBlockHandlerManager.AddHandler<TextCharacterMetaDataBlock>();
			DataBlockHandlerManager.AddHandler<TextDataBlock>();
			DataBlockHandlerManager.AddHandler<VanityItemsGroupDataBlock>();
			DataBlockHandlerManager.AddHandler<VanityItemsLayerDropsDataBlock>();
			DataBlockHandlerManager.AddHandler<VanityItemsTemplateDataBlock>();
			DataBlockHandlerManager.AddHandler<WardenObjectiveDataBlock>();
			DataBlockHandlerManager.AddHandler<WeaponAudioDataBlock>();
			DataBlockHandlerManager.AddHandler<WeaponDataBlock>();
			DataBlockHandlerManager.AddHandler<WeaponMuzzleFlashDataBlock>();
			DataBlockHandlerManager.AddHandler<WeaponShellCasingDataBlock>();
		}
	}
	[HarmonyPatch(typeof(GameDataInit), "ReInitialize")]
	internal static class DataBlockReInitPatch
	{
		[HarmonyPriority(600)]
		[HarmonyWrapSafe]
		private static void Prefix()
		{
			InheritanceResolverManager.ResetResolvers();
		}
	}
	[HarmonyPatch(typeof(GameDataInit), "Initialize")]
	internal static class DataBlockInitPatch
	{
		[HarmonyPriority(600)]
		[HarmonyWrapSafe]
		private static void Postfix()
		{
			InheritanceResolverManager.RunResolvers();
		}
	}
	[BepInPlugin("Dinorush.InheritanceDataBlocks", "InheritanceDataBlocks", "1.1.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public const string MODNAME = "InheritanceDataBlocks";

		public override void Load()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			IDBLogger.Log("Loading InheritanceDataBlocks");
			Configuration.Init();
			DataBlockHandlerManager.Init();
			new Harmony("InheritanceDataBlocks").PatchAll();
			IDBLogger.Log("Loaded InheritanceDataBlocks");
		}
	}
}
namespace InheritanceDataBlocks.Utils
{
	internal static class IDBLogger
	{
		private static readonly ManualLogSource logger = Logger.CreateLogSource("InheritanceDataBlocks");

		public static void Log(string format, params object[] args)
		{
			Log(string.Format(format, args));
		}

		public static void Log(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)8, (object)str);
			}
		}

		public static void Warning(string format, params object[] args)
		{
			Warning(string.Format(format, args));
		}

		public static void Warning(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)4, (object)str);
			}
		}

		public static void Error(string format, params object[] args)
		{
			Error(string.Format(format, args));
		}

		public static void Error(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)2, (object)str);
			}
		}

		public static void Debug(string format, params object[] args)
		{
			Debug(string.Format(format, args));
		}

		public static void Debug(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)32, (object)str);
			}
		}
	}
	public static class PropertyUtil
	{
		public static PropertyInfo? ToProperty(this string name, Type type, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public)
		{
			PropertyInfo property = type.GetProperty(name, flags);
			if (property == null || !property.CanWrite)
			{
				return null;
			}
			return property;
		}

		public static void CopyProperties<T>(T source, T target)
		{
			PropertyInfo[] properties = typeof(T).GetProperties();
			foreach (PropertyInfo propertyInfo in properties)
			{
				Type propertyType = propertyInfo.PropertyType;
				if (!propertyInfo.Name.Contains("_k__BackingField") && !(propertyType == typeof(IntPtr)) && propertyInfo.CanRead && propertyInfo.CanWrite)
				{
					propertyInfo.SetValue(target, propertyInfo.GetValue(source));
				}
			}
		}
	}
}
namespace InheritanceDataBlocks.Inheritance
{
	public class InheritanceNode<T>
	{
		public uint ID { get; private set; }

		public uint ParentID { get; private set; }

		public List<PropertyInfo> Properties { get; private set; }

		public T Data { get; private set; }

		public InheritanceNode(uint id, T data, List<PropertyInfo> properties, uint parentID)
		{
			ID = id;
			Properties = properties;
			Data = data;
			ParentID = parentID;
		}
	}
	public class InheritanceRoot<T>
	{
		private readonly Dictionary<uint, InheritanceNode<T>> _nodes = new Dictionary<uint, InheritanceNode<T>>();

		public void Clear()
		{
			_nodes.Clear();
		}

		public bool AddNode(uint ID, T data, List<PropertyInfo> properties, uint parentID)
		{
			return AddNode(new InheritanceNode<T>(ID, data, properties, parentID));
		}

		public bool AddNode(InheritanceNode<T> newNode)
		{
			for (InheritanceNode<T> valueOrDefault = _nodes.GetValueOrDefault(newNode.ParentID); valueOrDefault != null; valueOrDefault = _nodes.GetValueOrDefault(valueOrDefault.ParentID))
			{
				if (valueOrDefault.ParentID == newNode.ID)
				{
					string[] obj = new string[6]
					{
						"Error adding ID ",
						newNode.ID.ToString(),
						": dependency cycle detected with ID ",
						valueOrDefault.ID.ToString(),
						" on data ",
						null
					};
					T data = newNode.Data;
					obj[5] = ((data != null) ? data.GetType().Name : null);
					IDBLogger.Error(string.Concat(obj));
					return false;
				}
			}
			_nodes[newNode.ID] = newNode;
			return true;
		}

		public bool RemoveNode(uint ID)
		{
			return _nodes.Remove(ID);
		}

		public ICollection<uint> GetIDs()
		{
			return _nodes.Keys;
		}

		public InheritanceNode<T>? GetNode(uint ID)
		{
			return _nodes.GetValueOrDefault(ID);
		}

		public bool TryGetNode(uint ID, [MaybeNullWhen(false)] out InheritanceNode<T> node)
		{
			return _nodes.TryGetValue(ID, out node);
		}

		public LinkedList<InheritanceNode<T>>? GetInheritanceList(uint ID)
		{
			if (!_nodes.ContainsKey(ID))
			{
				return null;
			}
			LinkedList<InheritanceNode<T>> linkedList = new LinkedList<InheritanceNode<T>>();
			for (InheritanceNode<T> inheritanceNode = _nodes[ID]; inheritanceNode != null; inheritanceNode = _nodes.GetValueOrDefault(inheritanceNode.ParentID))
			{
				linkedList.AddFirst(inheritanceNode);
			}
			return linkedList;
		}

		public void DebugPrintAllPaths(string? groupName = null)
		{
			if (_nodes.Count == 0)
			{
				return;
			}
			IDBLogger.Log("Printing all inheritance chains" + ((groupName != null) ? (" for " + groupName) : ""));
			foreach (uint iD in GetIDs())
			{
				LinkedList<InheritanceNode<T>> inheritanceList = GetInheritanceList(iD);
				StringBuilder stringBuilder = new StringBuilder("ID " + iD + ": (Base) " + inheritanceList.First.Value.ParentID);
				foreach (InheritanceNode<T> item in inheritanceList)
				{
					stringBuilder.Append(" -> " + item.ID);
				}
				IDBLogger.Log(stringBuilder.ToString());
			}
		}
	}
	internal interface IResolver
	{
		void Reset();

		void Run();
	}
	internal sealed class InheritanceResolver<T> : IResolver where T : GameDataBlockBase<T>
	{
		public static InheritanceResolver<T> Instance = new InheritanceResolver<T>();

		private InheritanceRoot<T> _root = new InheritanceRoot<T>();

		private readonly Dictionary<string, PropertyInfo> _propertyCache = new Dictionary<string, PropertyInfo>();

		public InheritanceResolver()
		{
			InheritanceResolverManager.RegisterResolver(this);
		}

		internal static InheritanceRoot<T> GetRoot()
		{
			return Instance._root;
		}

		public void Reset()
		{
			_root.Clear();
		}

		public void Run()
		{
			foreach (uint iD in _root.GetIDs())
			{
				ResolveInheritance(iD);
			}
			if (Configuration.DebugChains)
			{
				_root.DebugPrintAllPaths(GameDataBlockBase<T>.m_fileNameNoExt);
			}
		}

		private void ResolveInheritance(uint ID)
		{
			LinkedList<InheritanceNode<T>> inheritanceList = _root.GetInheritanceList(ID);
			if (inheritanceList == null)
			{
				IDBLogger.Error("Inheritance list for ID " + ID + " is null! Block: " + GameDataBlockBase<T>.m_fileNameNoExt);
				return;
			}
			T block = GameDataBlockBase<T>.GetBlock(inheritanceList.First.Value.ParentID);
			if (block == null)
			{
				IDBLogger.Error("Error on ID " + ID + ": unable to find parent block with ID " + inheritanceList.First.Value.ParentID + " in " + GameDataBlockBase<T>.m_fileNameNoExt);
				return;
			}
			T val = (T)Activator.CreateInstance(typeof(T));
			PropertyUtil.CopyProperties(block, val);
			foreach (InheritanceNode<T> item in inheritanceList)
			{
				foreach (PropertyInfo property in item.Properties)
				{
					property.SetValue(val, property.GetValue(item.Data));
				}
			}
			PropertyUtil.CopyProperties(val, inheritanceList.Last.Value.Data);
		}

		public PropertyInfo? CacheProperty(Type blockType, string name)
		{
			if (_propertyCache.TryGetValue(name, out PropertyInfo value))
			{
				return value;
			}
			PropertyInfo propertyInfo = name.ToProperty(typeof(T));
			if (propertyInfo == null)
			{
				IDBLogger.Warning("Cannot find property \"" + name + "\" in " + blockType.Name);
				return null;
			}
			_propertyCache[name] = propertyInfo;
			return propertyInfo;
		}
	}
	internal static class InheritanceResolverManager
	{
		private static readonly List<IResolver> _resolvers = new List<IResolver>();

		public static void RegisterResolver(IResolver resolver)
		{
			_resolvers.Add(resolver);
		}

		public static void ResetResolvers()
		{
			_resolvers.ForEach(delegate(IResolver resolver)
			{
				resolver.Reset();
			});
		}

		public static void RunResolvers()
		{
			_resolvers.ForEach(delegate(IResolver resolver)
			{
				resolver.Run();
			});
		}
	}
}
namespace InheritanceDataBlocks.API
{
	public static class InheritanceAPI<T> where T : GameDataBlockBase<T>
	{
		public static PropertyInfo? CacheProperty(Type blockType, string name)
		{
			return InheritanceResolver<T>.Instance.CacheProperty(blockType, name);
		}

		public static void ApplyAllInheritance()
		{
			InheritanceResolver<T>.Instance.Run();
		}

		public static InheritanceRoot<T> GetRoot()
		{
			return InheritanceResolver<T>.GetRoot();
		}

		public static void AddDataBlock(T data, List<PropertyInfo> properties, uint parentID)
		{
			AddNode(((GameDataBlockBase<T>)data).persistentID, data, properties, parentID);
		}

		public static bool AddNode(uint ID, T data, List<PropertyInfo> properties, uint parentID)
		{
			return InheritanceResolver<T>.GetRoot().AddNode(ID, data, properties, parentID);
		}

		public static bool AddNode(InheritanceNode<T> node)
		{
			return InheritanceResolver<T>.GetRoot().AddNode(node);
		}

		public static bool RemoveNode(uint ID)
		{
			return InheritanceResolver<T>.GetRoot().RemoveNode(ID);
		}

		public static InheritanceNode<T>? GetNode(uint ID)
		{
			return InheritanceResolver<T>.GetRoot().GetNode(ID);
		}

		public static bool TryGetNode(uint ID, [MaybeNullWhen(false)] out InheritanceNode<T> node)
		{
			return InheritanceResolver<T>.GetRoot().TryGetNode(ID, out node);
		}

		public static LinkedList<InheritanceNode<T>>? GetInheritanceList(uint ID)
		{
			return InheritanceResolver<T>.GetRoot().GetInheritanceList(ID);
		}

		public static void DebugPrintAllPaths(string? groupName = null)
		{
			InheritanceResolver<T>.GetRoot().DebugPrintAllPaths(groupName);
		}
	}
}