Decompiled source of SkeletonBetterModels v0.1.1

SkeletonBetterModels.dll

Decompiled 6 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SkeletonBetterModels")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("SkeletonBetterModels")]
[assembly: AssemblyTitle("SkeletonBetterModels")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SkeletonBetterModels
{
	[BepInPlugin("sylphnox.skeletonbettermodels", "SkeletonBetterModels", "0.1.0.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "sylphnox.skeletonbettermodels";

		public const string PluginName = "SkeletonBetterModels";

		public const string PluginVersion = "0.1.0.6";

		internal static ManualLogSource Log;

		internal static AssetBundle Bundle;

		internal static GameObject SourcePrefab;

		internal static SkinnedMeshRenderer SourceRenderer;

		internal static Transform SourceHead;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty, "skeletonbettermodels");
			Bundle = AssetBundle.LoadFromFile(text);
			if (!Object.op_Implicit((Object)(object)Bundle))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("AssetBundle was not loaded: " + text));
				return;
			}
			SourcePrefab = ((IEnumerable<GameObject>)Bundle.LoadAllAssets<GameObject>()).FirstOrDefault((Func<GameObject, bool>)((GameObject go) => go.GetComponentsInChildren<SkinnedMeshRenderer>(true).Any((SkinnedMeshRenderer r) => r.bones != null && r.bones.Length >= 50)));
			if (!Object.op_Implicit((Object)(object)SourcePrefab))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"No rigged skeleton prefab exists in the AssetBundle.");
				return;
			}
			SourceRenderer = FindBodyRenderer(SourcePrefab);
			SourceHead = ((IEnumerable<Transform>)SourcePrefab.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Head"));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded test asset '" + ((Object)SourcePrefab).name + "': mesh=" + ((Object)SourceRenderer.sharedMesh).name + ", " + $"vertices={SourceRenderer.sharedMesh.vertexCount}, bones={SourceRenderer.bones.Length}"));
			_harmony = new Harmony("sylphnox.skeletonbettermodels");
			_harmony.PatchAll();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static SkinnedMeshRenderer FindBodyRenderer(GameObject root)
		{
			return ((IEnumerable<SkinnedMeshRenderer>)root.GetComponentsInChildren<SkinnedMeshRenderer>(true).OrderByDescending(delegate(SkinnedMeshRenderer r)
			{
				Transform[] bones = r.bones;
				return (bones != null) ? bones.Length : 0;
			})).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => Object.op_Implicit((Object)(object)r.sharedMesh) && r.bones != null && r.bones.Length >= 50));
		}

		internal static Transform Find(Transform root, string name)
		{
			return ((IEnumerable<Transform>)((Component)root).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == name));
		}

		internal static void ApplyToPrefab(GameObject prefab)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)SourceRenderer) || !Object.op_Implicit((Object)(object)SourceRenderer.sharedMesh))
			{
				return;
			}
			SkinnedMeshRenderer target = FindBodyRenderer(prefab);
			if (!Object.op_Implicit((Object)(object)target))
			{
				Log.LogWarning((object)(((Object)prefab).name + ": body SkinnedMeshRenderer was not found."));
				return;
			}
			Dictionary<string, Transform> dictionary = (from t in prefab.GetComponentsInChildren<Transform>(true)
				group t by ((Object)t).name).ToDictionary((IGrouping<string, Transform> group) => group.Key, (IGrouping<string, Transform> group) => group.First());
			Transform[] array = (Transform[])(object)new Transform[SourceRenderer.bones.Length];
			List<string> list = new List<string>();
			for (int num = 0; num < SourceRenderer.bones.Length; num++)
			{
				string name = ((Object)SourceRenderer.bones[num]).name;
				if (!dictionary.TryGetValue(name, out array[num]))
				{
					list.Add(name);
				}
			}
			if (list.Count > 0)
			{
				Log.LogError((object)(((Object)prefab).name + ": missing bones: " + string.Join(", ", list)));
				return;
			}
			Vector3 localPosition = ((Component)target).transform.localPosition;
			Quaternion localRotation = ((Component)target).transform.localRotation;
			Vector3 localScale = ((Component)target).transform.localScale;
			((Component)target).transform.localPosition = ((Component)SourceRenderer).transform.localPosition;
			((Component)target).transform.localRotation = ((Component)SourceRenderer).transform.localRotation;
			((Component)target).transform.localScale = ((Component)SourceRenderer).transform.localScale;
			target.bones = array;
			if (Object.op_Implicit((Object)(object)SourceRenderer.rootBone) && dictionary.TryGetValue(((Object)SourceRenderer.rootBone).name, out var value))
			{
				target.rootBone = value;
			}
			Mesh val = Object.Instantiate<Mesh>(SourceRenderer.sharedMesh);
			((Object)val).name = ((Object)SourceRenderer.sharedMesh).name + "_SBM_" + ((Object)prefab).name;
			val.bindposes = array.Select((Transform bone) => bone.worldToLocalMatrix * ((Component)target).transform.localToWorldMatrix).ToArray();
			target.sharedMesh = val;
			((Renderer)target).localBounds = ((Renderer)SourceRenderer).localBounds;
			target.updateWhenOffscreen = true;
			ApplyEye(prefab, target, "eye_l", "SBM_Eye_L");
			ApplyEye(prefab, target, "eye_r", "SBM_Eye_R");
			if (((Object)prefab).name.StartsWith("Skeleton_Hildir", StringComparison.Ordinal))
			{
				ApplyHeadFire(prefab, target);
			}
			ManualLogSource log = Log;
			string text = $"{((Object)prefab).name}: replaced mesh, vertices={target.sharedMesh.vertexCount}, ";
			string text2 = $"materials={((Renderer)target).sharedMaterials.Length}, bones={target.bones.Length}, ";
			string text3 = $"renderer transform {localPosition}/{((Quaternion)(ref localRotation)).eulerAngles}/{localScale} -> ";
			object arg = ((Component)target).transform.localPosition;
			Quaternion localRotation2 = ((Component)target).transform.localRotation;
			log.LogInfo((object)(text + text2 + text3 + $"{arg}/{((Quaternion)(ref localRotation2)).eulerAngles}/{((Component)target).transform.localScale}"));
		}

		private static Vector3 MapMarkerPosition(Transform marker, SkinnedMeshRenderer target)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			Vector3 val = ((Component)SourceRenderer).transform.InverseTransformPoint(marker.position);
			return ((Component)target).transform.TransformPoint(val);
		}

		private static Quaternion MapMarkerRotation(Transform marker, SkinnedMeshRenderer target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0025: 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)
			return ((Component)target).transform.rotation * Quaternion.Inverse(((Component)SourceRenderer).transform.rotation) * marker.rotation;
		}

		private static void ApplyEye(GameObject prefab, SkinnedMeshRenderer target, string eyeName, string markerName)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			Transform val = Find(prefab.transform, eyeName);
			Transform val2 = Find(SourcePrefab.transform, markerName);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				Log.LogWarning((object)(((Object)prefab).name + ": eye or marker missing (" + eyeName + "/" + markerName + ")."));
			}
			else
			{
				val.position = MapMarkerPosition(val2, target);
				val.rotation = MapMarkerRotation(val2, target) * Quaternion.Euler(-90f, 0f, 0f);
			}
		}

		private static void ApplyHeadFire(GameObject prefab, SkinnedMeshRenderer target)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Transform val = Find(prefab.transform, "fx_Torch_Carried");
			Transform val2 = Find(SourcePrefab.transform, "SBM_HeadFire");
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				Log.LogWarning((object)(((Object)prefab).name + ": head fire or marker missing."));
				return;
			}
			Transform parent = val.parent;
			object obj;
			if (!Object.op_Implicit((Object)(object)parent))
			{
				obj = null;
			}
			else
			{
				Light? obj2 = ((Component)parent).GetComponentsInChildren<Light>(true).FirstOrDefault();
				obj = ((obj2 != null) ? ((Component)obj2).transform : null);
			}
			Transform val3 = (Transform)obj;
			Vector3 val4 = (Object.op_Implicit((Object)(object)val3) ? (val3.position - val.position) : Vector3.zero);
			Vector3 val5 = (val.position = MapMarkerPosition(val2, target));
			if (Object.op_Implicit((Object)(object)val3))
			{
				val3.position = val5 + val4;
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneAwakePatch
	{
		private static void Postfix(ZNetScene __instance)
		{
			if (!Object.op_Implicit((Object)(object)Plugin.SourceRenderer))
			{
				return;
			}
			string[] array = new string[4] { "Skeleton", "Skeleton_Poison", "Skeleton_Hildir", "Skeleton_Hildir_nochest" };
			foreach (string text in array)
			{
				GameObject prefab = __instance.GetPrefab(text);
				if (Object.op_Implicit((Object)(object)prefab))
				{
					Plugin.ApplyToPrefab(prefab);
				}
				else
				{
					Plugin.Log.LogWarning((object)("Prefab was not found: " + text));
				}
			}
		}
	}
}