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