Decompiled source of HeadOffsetFixer v1.3.0

Mods/HeadOffsetFixer.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using HarmonyLib;
using HeadOffsetFixer;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using MelonLoader;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "HeadOffsetFixer", "1.3.0", "notnotnotswipez", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonPriority(300)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("HeadOffsetFixer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HeadOffsetFixer")]
[assembly: AssemblyTitle("HeadOffsetFixer")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 HeadOffsetFixer
{
	public class Core : MelonMod
	{
		public static Avatar headlessAvatarClone;

		public static Animator headlessAvatarCloneAnimator;

		public static List<SafeBonePairing> safeBonePairings = new List<SafeBonePairing>();

		public static List<SafeRendererPairing> safeRendererPairings = new List<SafeRendererPairing>();

		public static List<Renderer> selfRenderers = new List<Renderer>();

		public static List<Renderer> cloneAvatarRenderers = new List<Renderer>();

		public static bool ignoreSpectator = true;

		public static Camera lastBeginRenderCam;

		public override void OnInitializeMelon()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			RenderPipelineManager.beginCameraRendering += Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)delegate(ScriptableRenderContext ctx, Camera cam)
			{
				lastBeginRenderCam = cam;
				CheckRenderLoop(cam);
			});
			Page val = Page.Root.CreatePage("HeadOffsetFixer", Color.green, 0, true);
			val.CreateBool("Ignore Spectator Camera", Color.yellow, ignoreSpectator, (Action<bool>)delegate(bool b)
			{
				ignoreSpectator = b;
			});
		}

		public static void CheckRenderLoop(Camera cam)
		{
			if (!Player.HandsExist || !Object.op_Implicit((Object)(object)Player.Avatar))
			{
				return;
			}
			if (((Object)cam).name.Equals("Headset") || (((Object)cam).name.Equals("Spectator Camera") && ignoreSpectator))
			{
				ToggleAvatarVisibility(selfRenderers, show: true);
				if (Object.op_Implicit((Object)(object)headlessAvatarClone))
				{
					ToggleAvatarVisibility(cloneAvatarRenderers, show: false);
				}
			}
			else if (Object.op_Implicit((Object)(object)headlessAvatarClone))
			{
				ToggleAvatarVisibility(selfRenderers, show: false);
				ToggleAvatarVisibility(cloneAvatarRenderers, show: true);
			}
			else
			{
				ToggleAvatarVisibility(selfRenderers, show: true);
			}
		}

		public static void EnforceVisibility(bool showClone)
		{
			if (!Player.HandsExist || !Object.op_Implicit((Object)(object)Player.Avatar))
			{
				return;
			}
			if (showClone)
			{
				if (Object.op_Implicit((Object)(object)headlessAvatarClone))
				{
					ToggleAvatarVisibility(selfRenderers, show: false);
					ToggleAvatarVisibility(cloneAvatarRenderers, show: true);
				}
				else
				{
					ToggleAvatarVisibility(selfRenderers, show: true);
				}
			}
			else
			{
				ToggleAvatarVisibility(selfRenderers, show: true);
				if (Object.op_Implicit((Object)(object)headlessAvatarClone))
				{
					ToggleAvatarVisibility(cloneAvatarRenderers, show: false);
				}
			}
		}

		private static void ToggleAvatarVisibility(List<Renderer> renderers, bool show)
		{
			foreach (Renderer renderer in renderers)
			{
				renderer.forceRenderingOff = !show;
			}
		}
	}
	public struct SafeBonePairing
	{
		public Transform sourceBone;

		public Transform destinationBone;

		public void Copy()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			destinationBone.SetPositionAndRotation(sourceBone.position, sourceBone.rotation);
		}
	}
	public struct SafeRendererPairing
	{
		public Renderer sourceRenderer;

		public Renderer destinationRenderer;

		public bool forceDisable;

		public void Copy()
		{
			destinationRenderer.materials = sourceRenderer.materials;
			if (forceDisable)
			{
				destinationRenderer.forceRenderingOff = true;
			}
			else
			{
				destinationRenderer.enabled = sourceRenderer.enabled && ((Component)sourceRenderer).gameObject.activeInHierarchy;
			}
		}
	}
	[HarmonyPatch(typeof(UniversalRenderPipeline), "RenderSingleCamera", new Type[]
	{
		typeof(ScriptableRenderContext),
		typeof(Camera)
	})]
	public class RenderSingleCameraPatch
	{
		public static void Prefix(ScriptableRenderContext context, Camera camera)
		{
			Core.EnforceVisibility(showClone: true);
		}
	}
	[HarmonyPatch(typeof(UniversalRenderPipeline), "RenderSingleCamera", new Type[]
	{
		typeof(ScriptableRenderContext),
		typeof(Camera)
	})]
	public class RenderSingleCameraPatchPostfix
	{
		public static void Postfix(ScriptableRenderContext context, Camera camera)
		{
			Core.CheckRenderLoop(Core.lastBeginRenderCam);
		}
	}
	[HarmonyPatch(typeof(PlayerAvatarArt), "UpdateAvatarHead")]
	public class PlayerArtPatch
	{
		public static void Prefix(PlayerAvatarArt __instance)
		{
			if (((Object)((Rig)__instance._openCtrlRig).manager).GetInstanceID() != ((Object)Player.RigManager).GetInstanceID() || !Object.op_Implicit((Object)(object)Core.headlessAvatarCloneAnimator))
			{
				return;
			}
			foreach (SafeBonePairing safeBonePairing in Core.safeBonePairings)
			{
				safeBonePairing.Copy();
			}
			foreach (SafeRendererPairing safeRendererPairing in Core.safeRendererPairings)
			{
				safeRendererPairing.Copy();
			}
		}
	}
	[HarmonyPatch(typeof(ArtRig), "SetArtOutputAvatar")]
	public class RigmanagerAvatarSwitchEventPatch
	{
		public static void Postfix(ArtRig __instance, PhysicsRig inRig, Avatar avatar)
		{
			if (Object.op_Implicit((Object)(object)Player.RigManager))
			{
				if (((Object)((Rig)inRig).manager).GetInstanceID() == ((Object)Player.RigManager).GetInstanceID())
				{
					if (Object.op_Implicit((Object)(object)Core.headlessAvatarClone))
					{
						Object.DestroyImmediate((Object)(object)((Component)Core.headlessAvatarClone).gameObject);
					}
					Core.selfRenderers.Clear();
					Core.cloneAvatarRenderers.Clear();
					MelonCoroutines.Start(WaitForRigToUpdateAvatar(((Rig)inRig).manager));
				}
			}
			else
			{
				Core.selfRenderers.Clear();
				Core.cloneAvatarRenderers.Clear();
			}
		}

		private static IEnumerator WaitForRigToUpdateAvatar(RigManager manager)
		{
			for (int i = 0; i < 3; i++)
			{
				yield return null;
			}
			if (!Object.op_Implicit((Object)(object)manager.avatar))
			{
				yield break;
			}
			foreach (Renderer selfRenderer in ((Component)manager.avatar).GetComponentsInChildren<Renderer>(true))
			{
				Core.selfRenderers.Add(selfRenderer);
			}
			GameObject disabledObject = new GameObject("DISABLED CONTAINER");
			disabledObject.SetActive(false);
			GameObject headlessCloneObject = Object.Instantiate<GameObject>(((Component)manager.avatar).gameObject, disabledObject.transform);
			CleanClone(headlessCloneObject);
			headlessCloneObject.transform.parent = null;
			Object.Destroy((Object)(object)disabledObject);
			Core.headlessAvatarClone = headlessCloneObject.GetComponentInChildren<Avatar>();
			Core.headlessAvatarCloneAnimator = Core.headlessAvatarClone.animator;
			foreach (SkinnedMeshRenderer hairMesh in (Il2CppArrayBase<SkinnedMeshRenderer>)(object)Core.headlessAvatarClone.hairMeshes)
			{
				((Renderer)hairMesh).shadowCastingMode = (ShadowCastingMode)1;
			}
			foreach (Renderer cloneRenderer in ((Component)Core.headlessAvatarClone).GetComponentsInChildren<Renderer>(true))
			{
				Core.cloneAvatarRenderers.Add(cloneRenderer);
			}
			SaveAllValidBones(manager.avatar.animator, Core.headlessAvatarCloneAnimator);
			SaveAllValidRenderers(((Component)manager.avatar).gameObject, headlessCloneObject);
			((Object)headlessCloneObject).name = "HEADFIX DISPLAY CLONE";
		}

		private static void CleanClone(GameObject cloneAvatar)
		{
			foreach (MonoBehaviour componentsInChild in cloneAvatar.GetComponentsInChildren<MonoBehaviour>(true))
			{
				if (!Object.op_Implicit((Object)(object)((Il2CppObjectBase)componentsInChild).TryCast<Avatar>()))
				{
					Object.DestroyImmediate((Object)(object)componentsInChild);
				}
			}
			foreach (ConfigurableJoint componentsInChild2 in cloneAvatar.GetComponentsInChildren<ConfigurableJoint>(true))
			{
				Object.DestroyImmediate((Object)(object)componentsInChild2);
			}
			foreach (Collider componentsInChild3 in cloneAvatar.GetComponentsInChildren<Collider>(true))
			{
				Object.DestroyImmediate((Object)(object)componentsInChild3);
			}
			foreach (Rigidbody componentsInChild4 in cloneAvatar.GetComponentsInChildren<Rigidbody>(true))
			{
				Object.DestroyImmediate((Object)(object)componentsInChild4);
			}
			foreach (InteractableHost componentsInChild5 in cloneAvatar.GetComponentsInChildren<InteractableHost>(true))
			{
				Object.DestroyImmediate((Object)(object)componentsInChild5);
			}
		}

		private static void SaveAllValidBones(Animator source, Animator destination)
		{
			Core.safeBonePairings.Clear();
			Transform[] allBones = GetAllBones(((Component)source).gameObject);
			Transform[] allBones2 = GetAllBones(((Component)destination).gameObject);
			for (int i = 0; i < allBones.Length; i++)
			{
				Core.safeBonePairings.Add(new SafeBonePairing
				{
					sourceBone = allBones[i],
					destinationBone = allBones2[i]
				});
				allBones2[i].parent = ((Component)destination).gameObject.transform;
			}
		}

		private static Transform[] GetAllBones(GameObject root)
		{
			Dictionary<int, Transform> dictionary = new Dictionary<int, Transform>();
			foreach (SkinnedMeshRenderer componentsInChild in root.GetComponentsInChildren<SkinnedMeshRenderer>(true))
			{
				Il2CppReferenceArray<Transform> bones = componentsInChild.bones;
				foreach (Transform item in (Il2CppArrayBase<Transform>)(object)bones)
				{
					if (!dictionary.ContainsKey(((Object)item).GetInstanceID()))
					{
						dictionary.Add(((Object)item).GetInstanceID(), item);
					}
				}
			}
			return dictionary.Values.ToArray();
		}

		private static void SaveAllValidRenderers(GameObject source, GameObject destination)
		{
			Core.safeRendererPairings.Clear();
			Il2CppArrayBase<Renderer> componentsInChildren = source.GetComponentsInChildren<Renderer>(true);
			Il2CppArrayBase<Renderer> componentsInChildren2 = destination.GetComponentsInChildren<Renderer>(true);
			List<Transform> list = new List<Transform>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				bool forceDisable = false;
				Renderer val = componentsInChildren2[i];
				if (Object.op_Implicit((Object)(object)val.material) && ((Object)val.material.shader).name == "SLZ/Icon Billboard")
				{
					forceDisable = true;
				}
				Core.safeRendererPairings.Add(new SafeRendererPairing
				{
					sourceRenderer = componentsInChildren[i],
					destinationRenderer = componentsInChildren2[i],
					forceDisable = forceDisable
				});
				((Component)componentsInChildren2[i]).gameObject.transform.parent = destination.transform;
				((Component)componentsInChildren2[i]).gameObject.SetActive(true);
				list.Add(((Component)componentsInChildren2[i]).gameObject.transform);
			}
		}
	}
}