Decompiled source of GhostHats v0.1.0

plugins\GhostHats.dll

Decompiled 5 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("GhostHats")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+58a883f81ab0a4fcb6daeb34c041f97c31e23c98")]
[assembly: AssemblyProduct("GhostHats")]
[assembly: AssemblyTitle("GhostHats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[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 GhostHats
{
	internal class GhostHat : MonoBehaviour
	{
		internal static void Attach(PlayerGhost ghost)
		{
			if (!((Object)(object)ghost == (Object)null) && !((Object)(object)ghost.m_owner == (Object)null) && !((Object)(object)((Component)ghost).GetComponent<GhostHat>() != (Object)null))
			{
				Character owner = ghost.m_owner;
				PhotonView photonView = ((MonoBehaviourPun)owner).photonView;
				if (!((Object)(object)photonView != (Object)null) || !photonView.IsMine)
				{
					((Component)ghost).gameObject.AddComponent<GhostHat>().Build(ghost, owner);
				}
			}
		}

		private void Build(PlayerGhost ghost, Character owner)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: 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_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			Renderer val = ResolveHatRenderer(owner);
			if ((Object)(object)val == (Object)null)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			CustomizationRefs refs = owner.refs.customization.refs;
			if (!TryFaceFrame(refs.EyeRenderers, refs.mouthRenderer, out var center, out var rotation, out var span) || !TryFaceFrame(ghost.EyeRenderers, ghost.mouthRenderer, out var center2, out var rotation2, out var span2))
			{
				Plugin.Log.LogWarning((object)"Could not measure a face (two eyes + a mouth) on the character or the ghost, so there is nothing to line the hat up with. Did the game update?");
				Object.Destroy((Object)(object)this);
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject);
			((Object)val2).name = "GhostHat";
			val2.SetActive(true);
			Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			SetLayerRecursively(val2.transform, GhostLayer(ghost));
			Quaternion val3 = rotation2 * Quaternion.Inverse(rotation);
			float num = span2 / span;
			Transform transform = ((Component)val).transform;
			Vector3 val4 = center2 + val3 * (transform.position - center) * num;
			Quaternion val5 = val3 * transform.rotation;
			Vector3 val6 = transform.lossyScale * num;
			Transform transform2 = ((Component)ghost).transform;
			Vector3 lossyScale = transform2.lossyScale;
			Transform transform3 = val2.transform;
			transform3.SetParent(transform2, false);
			transform3.localPosition = transform2.InverseTransformPoint(val4);
			transform3.localRotation = Quaternion.Inverse(transform2.rotation) * val5;
			transform3.localScale = new Vector3(val6.x / NonZero(lossyScale.x), val6.y / NonZero(lossyScale.y), val6.z / NonZero(lossyScale.z));
			Log($"Hat '{((Object)val).name}' on {owner.characterName}'s ghost: scale ratio {num:F3}, " + $"local pos {transform3.localPosition}.");
		}

		private static Renderer ResolveHatRenderer(Character owner)
		{
			CharacterCustomization val = ((owner.refs != null) ? owner.refs.customization : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.refs == (Object)null || val.refs.playerHats == null)
			{
				Log(owner.characterName + " has no customization refs, so no hat.");
				return null;
			}
			Renderer[] playerHats = val.refs.playerHats;
			PersistentPlayerData playerData = GameHandler.GetService<PersistentPlayerDataService>().GetPlayerData(((MonoBehaviourPun)owner).photonView.Owner);
			if (playerData == null)
			{
				return null;
			}
			int num = playerData.customizationData.currentHat;
			Customization instance = Singleton<Customization>.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				CustomizationOption val2 = instance.fits[CharacterCustomization.GetFitIndex(playerData)];
				if ((Object)(object)val2 != (Object)null && val2.overrideHat)
				{
					num = val2.overrideHatIndex;
				}
				if (num >= 0 && num < instance.hats.Length && (Object)(object)instance.hats[num] != (Object)null && instance.hats[num].isBlank)
				{
					Log(owner.characterName + " is not wearing a hat.");
					return null;
				}
			}
			if (num < 0 || num >= playerHats.Length)
			{
				Log($"Hat index {num} is out of range (0..{playerHats.Length - 1}), so no hat.");
				return null;
			}
			Renderer val3 = playerHats[num];
			if ((Object)(object)val3 == (Object)null || !HasVisibleMesh(val3))
			{
				Log($"Hat index {num} has no mesh, so no hat.");
				return null;
			}
			return val3;
		}

		private static bool TryFaceFrame(Renderer[] eyes, Renderer mouth, out Vector3 center, out Quaternion rotation, out float span)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			center = Vector3.zero;
			rotation = Quaternion.identity;
			span = 0f;
			if (eyes == null || eyes.Length < 2 || (Object)(object)mouth == (Object)null)
			{
				return false;
			}
			Vector3 val = Vector3.zero;
			Vector3 val2 = Vector3.zero;
			Bounds bounds;
			for (int i = 0; i < eyes.Length; i++)
			{
				if ((Object)(object)eyes[i] == (Object)null)
				{
					continue;
				}
				for (int j = i + 1; j < eyes.Length; j++)
				{
					if (!((Object)(object)eyes[j] == (Object)null))
					{
						bounds = eyes[i].bounds;
						Vector3 center2 = ((Bounds)(ref bounds)).center;
						bounds = eyes[j].bounds;
						float num = Vector3.Distance(center2, ((Bounds)(ref bounds)).center);
						if (!(num <= span))
						{
							span = num;
							bounds = eyes[i].bounds;
							val = ((Bounds)(ref bounds)).center;
							bounds = eyes[j].bounds;
							val2 = ((Bounds)(ref bounds)).center;
						}
					}
				}
			}
			if (span < 0.0001f)
			{
				return false;
			}
			center = (val + val2) * 0.5f;
			Vector3 val3 = (val2 - val) / span;
			Vector3 val4 = center;
			bounds = mouth.bounds;
			Vector3 val5 = Vector3.ProjectOnPlane(val4 - ((Bounds)(ref bounds)).center, val3);
			if (((Vector3)(ref val5)).sqrMagnitude < 1E-08f)
			{
				return false;
			}
			((Vector3)(ref val5)).Normalize();
			rotation = Quaternion.LookRotation(Vector3.Cross(val3, val5), val5);
			return true;
		}

		private static int GhostLayer(PlayerGhost ghost)
		{
			Renderer[] playerRenderers = ghost.PlayerRenderers;
			if (playerRenderers != null)
			{
				for (int i = 0; i < playerRenderers.Length; i++)
				{
					if ((Object)(object)playerRenderers[i] != (Object)null)
					{
						return ((Component)playerRenderers[i]).gameObject.layer;
					}
				}
			}
			return ((Component)ghost).gameObject.layer;
		}

		private static void SetLayerRecursively(Transform t, int layer)
		{
			((Component)t).gameObject.layer = layer;
			for (int i = 0; i < t.childCount; i++)
			{
				SetLayerRecursively(t.GetChild(i), layer);
			}
		}

		private static bool HasVisibleMesh(Renderer renderer)
		{
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
			{
				return true;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMesh != (Object)null)
			{
				return true;
			}
			if ((Object)(object)component == (Object)null)
			{
				return (Object)(object)val == (Object)null;
			}
			return false;
		}

		private static float NonZero(float v)
		{
			if (!(Mathf.Abs(v) < 1E-05f))
			{
				return v;
			}
			return 1f;
		}

		private static void Log(string message)
		{
			Plugin.Log.LogDebug((object)message);
		}
	}
	[HarmonyPatch(typeof(PlayerGhost), "RPCA_InitGhost")]
	internal static class PlayerGhostInitPatch
	{
		private static void Postfix(PlayerGhost __instance)
		{
			try
			{
				GhostHat.Attach(__instance);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to put a hat on a ghost: {arg}");
			}
		}
	}
	[BepInPlugin("com.exoflex.ghosthats", "GhostHats", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.exoflex.ghosthats";

		public const string PluginName = "GhostHats";

		public const string PluginVersion = "0.1.0";

		private Harmony harmony;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("com.exoflex.ghosthats");
			harmony.PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"GhostHats 0.1.0 loaded. Death is no excuse for bad fashion.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}