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);
}
}
}