Decompiled source of ADrinkWithFriends v1.0.0

ADrinkWithFriends.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("A-Drink-with-Friends")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("A-Drink-with-Friends")]
[assembly: AssemblyTitle("A-Drink-with-Friends")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace JellyInteractMod;

internal sealed class JellyAnimator : MonoBehaviour
{
	private sealed class VisualNode
	{
		public Transform Node;

		public Transform Parent;

		public Renderer Source;

		public Renderer ProxyRenderer;

		public Matrix4x4 BaseLocal;

		public bool HasApplied;

		public Vector3 LastPos;

		public Quaternion LastRot;

		public Vector3 LastScale;

		public Vector3 InitialScale;
	}

	private readonly List<VisualNode> _nodes = new List<VisualNode>();

	private readonly List<GameObject> _proxies = new List<GameObject>();

	private readonly List<Renderer> _hidden = new List<Renderer>();

	private Transform _root;

	private MonoBehaviour _source;

	private bool _isCharacter;

	private Vector3 _localCenter;

	private Vector3 _localMin;

	private Vector3 _localMax;

	private bool _ready;

	private bool _applied;

	private float _driftTimer;

	private bool _driftReported;

	internal string Report = "(not built)";

	private static readonly string[] EffectKeywords = new string[5] { "VFX", "Particle", "Trail", "Spark", "Smoke" };

	private static readonly string[] HandKeywords = new string[1] { "Hand" };

	internal bool Ready => _ready;

	private bool AllowRotation
	{
		get
		{
			if (Plugin.RotationEnabled)
			{
				if (_isCharacter)
				{
					return Plugin.RotateCharacters.Value;
				}
				return true;
			}
			return false;
		}
	}

	internal bool Build(MonoBehaviour source)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: 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_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: 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)
		//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
		_source = source;
		_root = ((Component)this).transform;
		_isCharacter = source is CharacterInteractible;
		_nodes.Clear();
		_ready = false;
		_applied = false;
		Renderer[] componentsInChildren;
		try
		{
			componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
		}
		catch
		{
			return false;
		}
		if (componentsInChildren == null || componentsInChildren.Length == 0)
		{
			return false;
		}
		if (!TryComputeLocalBounds(componentsInChildren, out var bmin, out var bmax))
		{
			return false;
		}
		_localMin = bmin;
		_localMax = bmax;
		_localCenter = (bmin + bmax) * 0.5f;
		float num = Mathf.Max(0.0005f, bmax.y - bmin.y);
		List<Transform> list = new List<Transform>();
		HashSet<Transform> hashSet = new HashSet<Transform>();
		Renderer[] array = componentsInChildren;
		foreach (Renderer val in array)
		{
			if ((Object)(object)val == (Object)null || IsDecorative(val) || (_source is CharacterInteractible && (Object)(object)((Component)val).GetComponentInParent<BackpackOnBackVisuals>() != (Object)null))
			{
				continue;
			}
			bool bonePath;
			Transform val2 = ResolveVisualNode(val, out bonePath);
			if (!((Object)(object)val2 == (Object)null))
			{
				list.Add(val2);
				if (bonePath)
				{
					hashSet.Add(val2);
				}
			}
		}
		if (list.Count == 0)
		{
			return false;
		}
		list.Sort((Transform a, Transform b) => DepthInRoot(a).CompareTo(DepthInRoot(b)));
		List<Transform> list2 = new List<Transform>();
		foreach (Transform item in list)
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			bool flag = false;
			foreach (Transform item2 in list2)
			{
				if ((Object)(object)item == (Object)(object)item2 || item.IsChildOf(item2))
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				list2.Add(item);
			}
		}
		int num2 = 0;
		int num3 = 0;
		bool flag2 = true;
		StringBuilder stringBuilder = new StringBuilder();
		foreach (Transform item3 in list2)
		{
			if ((Object)(object)item3 == (Object)null)
			{
				continue;
			}
			bool flag3 = (Object)(object)item3 == (Object)(object)_root;
			bool flag4 = hashSet.Contains(item3);
			bool flag5 = HasColliderInSubtree(item3);
			JellyAnimator componentInParent = ((Component)item3).GetComponentInParent<JellyAnimator>();
			if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)this)
			{
				num3++;
				if (Plugin.Diagnose.Value)
				{
					stringBuilder.Append("[busy ").Append(((Object)item3).name).Append("] ");
				}
				continue;
			}
			if (Plugin.Diagnose.Value)
			{
				stringBuilder.Append(((Object)item3).name).Append(" ");
			}
			if (Plugin.ProtectColliders.Value && !flag3 && !flag5)
			{
				AddNode(item3);
			}
			else if (Plugin.ProtectColliders.Value)
			{
				int made;
				if (flag4 && !flag3)
				{
					AddNode(item3);
					flag2 = false;
				}
				else if (TryBuildProxySubtree(item3, out made))
				{
					num2 += made;
				}
				else
				{
					num3++;
				}
			}
			else if (flag3 && (Object)(object)((Component)item3).GetComponent<PhotonView>() != (Object)null)
			{
				num3++;
			}
			else
			{
				AddNode(item3);
				if (flag3 || flag5)
				{
					flag2 = false;
				}
			}
		}
		_ready = _nodes.Count > 0;
		object[] obj2 = new object[9]
		{
			((Object)(object)source != (Object)null) ? ((object)source).GetType().Name : "?",
			componentsInChildren.Length,
			_nodes.Count,
			num2,
			num3,
			flag2,
			null,
			null,
			null
		};
		Vector3 val3 = _root.TransformPoint(_localCenter);
		obj2[6] = ((Vector3)(ref val3)).ToString("F2");
		obj2[7] = num;
		obj2[8] = (Plugin.Diagnose.Value ? (" || " + stringBuilder) : "");
		Report = string.Format("type={0} renderers={1} nodes={2} proxy={3} skip={4} safe={5} pivotW={6} h={7:F2}{8}", obj2);
		return _ready;
	}

	private void AddNode(Transform t)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		_nodes.Add(new VisualNode
		{
			Node = t,
			Parent = t.parent,
			Source = null,
			BaseLocal = LocalOf(t),
			HasApplied = false,
			InitialScale = t.localScale
		});
	}

	private void AddProxyNode(GameObject proxy, Renderer source)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		_nodes.Add(new VisualNode
		{
			Node = proxy.transform,
			Parent = proxy.transform.parent,
			Source = source,
			ProxyRenderer = proxy.GetComponent<Renderer>(),
			BaseLocal = Matrix4x4.identity,
			HasApplied = false
		});
	}

	private static Matrix4x4 LocalOf(Transform t)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return Matrix4x4.TRS(t.localPosition, t.localRotation, t.localScale);
	}

	private static bool HasColliderInSubtree(Transform t)
	{
		try
		{
			return (Object)(object)((Component)t).GetComponentInChildren<Collider>(true) != (Object)null;
		}
		catch
		{
			return true;
		}
	}

	private bool TryComputeLocalBounds(Renderer[] renderers, out Vector3 bmin, out Vector3 bmax)
	{
		//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_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: 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_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: 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_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//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_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		bmin = Vector3.zero;
		bmax = Vector3.zero;
		Matrix4x4 worldToLocalMatrix = _root.worldToLocalMatrix;
		Vector3 val3 = default(Vector3);
		for (int i = 0; i < 3; i++)
		{
			bool flag = false;
			foreach (Renderer val in renderers)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				bool flag2 = val is MeshRenderer || val is SkinnedMeshRenderer;
				if ((i == 0 && (!flag2 || IsDecorative(val))) || (i == 1 && !flag2))
				{
					continue;
				}
				Bounds localBounds;
				Matrix4x4 val2;
				try
				{
					localBounds = val.localBounds;
					val2 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
				}
				catch
				{
					continue;
				}
				if (((Bounds)(ref localBounds)).size == Vector3.zero)
				{
					continue;
				}
				for (int k = 0; k < 8; k++)
				{
					((Vector3)(ref val3))..ctor(((k & 1) == 0) ? ((Bounds)(ref localBounds)).min.x : ((Bounds)(ref localBounds)).max.x, ((k & 2) == 0) ? ((Bounds)(ref localBounds)).min.y : ((Bounds)(ref localBounds)).max.y, ((k & 4) == 0) ? ((Bounds)(ref localBounds)).min.z : ((Bounds)(ref localBounds)).max.z);
					Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(val3);
					if (!flag)
					{
						bmin = val4;
						bmax = val4;
						flag = true;
					}
					else
					{
						bmin = Vector3.Min(bmin, val4);
						bmax = Vector3.Max(bmax, val4);
					}
				}
			}
			if (flag)
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsEffect(Renderer r)
	{
		if (r is ParticleSystemRenderer || r is TrailRenderer || r is LineRenderer)
		{
			return true;
		}
		return HasKeywordUp(((Component)r).transform, EffectKeywords, 6);
	}

	private static bool IsDecorative(Renderer r)
	{
		if (!IsEffect(r))
		{
			return HasKeywordUp(((Component)r).transform, HandKeywords, 6);
		}
		return true;
	}

	private static bool HasKeywordUp(Transform t, string[] keys, int maxDepth)
	{
		int num = 0;
		while ((Object)(object)t != (Object)null && num++ < maxDepth)
		{
			string name = ((Object)t).name;
			if (!string.IsNullOrEmpty(name))
			{
				for (int i = 0; i < keys.Length; i++)
				{
					if (name.IndexOf(keys[i], StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			t = t.parent;
		}
		return false;
	}

	private Transform ResolveVisualNode(Renderer r, out bool bonePath)
	{
		bonePath = false;
		SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((r is SkinnedMeshRenderer) ? r : null);
		if (val != null)
		{
			Transform rootBone = val.rootBone;
			if ((Object)(object)rootBone != (Object)null)
			{
				Transform val2 = rootBone;
				while ((Object)(object)val2.parent != (Object)null && (Object)(object)val2.parent != (Object)(object)_root && val2.parent.IsChildOf(_root))
				{
					val2 = val2.parent;
				}
				if ((Object)(object)val2 != (Object)(object)_root && val2.IsChildOf(_root))
				{
					bonePath = true;
					return val2;
				}
				return null;
			}
		}
		return ((Component)r).transform;
	}

	private bool TryBuildProxySubtree(Transform t, out int made)
	{
		made = 0;
		List<GameObject> list = new List<GameObject>();
		List<Renderer> list2 = new List<Renderer>();
		MeshRenderer[] componentsInChildren;
		try
		{
			componentsInChildren = ((Component)t).GetComponentsInChildren<MeshRenderer>(true);
		}
		catch
		{
			return false;
		}
		if (componentsInChildren == null || componentsInChildren.Length == 0)
		{
			return false;
		}
		MeshRenderer[] array = componentsInChildren;
		foreach (MeshRenderer val in array)
		{
			if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled && ((Component)val).gameObject.activeInHierarchy)
			{
				MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
				{
					Rollback(list);
					return false;
				}
				GameObject val2 = MakeProxy(val, component);
				if ((Object)(object)val2 == (Object)null)
				{
					Rollback(list);
					return false;
				}
				list.Add(val2);
				list2.Add((Renderer)(object)val);
			}
		}
		if (list.Count == 0)
		{
			Rollback(list);
			return false;
		}
		for (int j = 0; j < list2.Count; j++)
		{
			list2[j].enabled = false;
			_hidden.Add(list2[j]);
		}
		for (int k = 0; k < list.Count; k++)
		{
			_proxies.Add(list[k]);
			AddProxyNode(list[k], list2[k]);
			made++;
		}
		return true;
	}

	private GameObject MakeProxy(MeshRenderer mr, MeshFilter mf)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Expected O, but got Unknown
		try
		{
			GameObject val = new GameObject("JellyProxy");
			val.layer = ((Component)mr).gameObject.layer;
			val.transform.SetPositionAndRotation(((Component)mr).transform.position, ((Component)mr).transform.rotation);
			val.transform.localScale = ((Component)mr).transform.lossyScale;
			val.transform.SetParent(_root, true);
			val.AddComponent<MeshFilter>().sharedMesh = mf.sharedMesh;
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			((Renderer)val2).sharedMaterials = ((Renderer)mr).sharedMaterials;
			((Renderer)val2).shadowCastingMode = ((Renderer)mr).shadowCastingMode;
			((Renderer)val2).receiveShadows = ((Renderer)mr).receiveShadows;
			((Renderer)val2).lightProbeUsage = ((Renderer)mr).lightProbeUsage;
			((Renderer)val2).reflectionProbeUsage = ((Renderer)mr).reflectionProbeUsage;
			((Renderer)val2).allowOcclusionWhenDynamic = ((Renderer)mr).allowOcclusionWhenDynamic;
			try
			{
				((Renderer)val2).renderingLayerMask = ((Renderer)mr).renderingLayerMask;
			}
			catch
			{
			}
			MaterialPropertyBlock val3 = new MaterialPropertyBlock();
			((Renderer)mr).GetPropertyBlock(val3);
			((Renderer)val2).SetPropertyBlock(val3);
			return val;
		}
		catch
		{
			return null;
		}
	}

	private static void Rollback(List<GameObject> created)
	{
		for (int i = 0; i < created.Count; i++)
		{
			if ((Object)(object)created[i] != (Object)null)
			{
				Object.Destroy((Object)(object)created[i]);
			}
		}
		created.Clear();
	}

	private string BuildPath(Transform t)
	{
		StringBuilder stringBuilder = new StringBuilder(((Object)t).name);
		Transform parent = t.parent;
		int num = 0;
		while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)_root && num++ < 8)
		{
			stringBuilder.Insert(0, ((Object)parent).name + "/");
			parent = parent.parent;
		}
		return stringBuilder.ToString();
	}

	private int DepthInRoot(Transform t)
	{
		int num = 0;
		Transform val = t;
		while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_root)
		{
			num++;
			val = val.parent;
		}
		return num;
	}

	private void LateUpdate()
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		if (!_ready)
		{
			return;
		}
		if (!Plugin.Animating || !Plugin.ShouldAffect(_source) || (!AllowRotation && !Plugin.StretchEnabled))
		{
			if (_applied)
			{
				ApplyMatrix(Matrix4x4.identity);
				_applied = false;
			}
			return;
		}
		ApplyMatrix(BuildMatrix(Plugin.PhaseValue, Plugin.StretchValue));
		_applied = true;
		if (Plugin.Diagnose.Value)
		{
			CheckDrift();
		}
	}

	private void CheckDrift()
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: 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)
		if (_driftReported || (Object)(object)Plugin.Instance == (Object)null)
		{
			return;
		}
		_driftTimer += Time.deltaTime;
		if (_driftTimer < 1f)
		{
			return;
		}
		_driftTimer = 0f;
		for (int i = 0; i < _nodes.Count; i++)
		{
			VisualNode visualNode = _nodes[i];
			if (!((Object)(object)visualNode.Node == (Object)null) && !((Object)(object)visualNode.Source != (Object)null))
			{
				Vector3 lossyScale = ((Matrix4x4)(ref visualNode.BaseLocal)).lossyScale;
				float num = lossyScale.y / Mathf.Max(0.0001f, Mathf.Abs(visualNode.InitialScale.y));
				float num2 = lossyScale.x / Mathf.Max(0.0001f, Mathf.Abs(visualNode.InitialScale.x));
				if (num > 1.3f || num < 0.77f || num2 > 1.3f || num2 < 0.77f)
				{
					_driftReported = true;
					Plugin.Instance.Logger.LogWarning((object)("[Jelly] DRIFT " + ((Object)this).name + " node=" + ((Object)visualNode.Node).name + " baseScale=" + ((Vector3)(ref lossyScale)).ToString("F3") + " initial=" + ((Vector3)(ref visualNode.InitialScale)).ToString("F3")));
					break;
				}
			}
		}
	}

	private Matrix4x4 BuildMatrix(float phase, float stretch)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: 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_0063: 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_0139: 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_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: 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_014f: 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_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: 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_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: 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_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: 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_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: 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_00ec: 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)
		float num = Mathf.Max(0.05f, Plugin.RotationTurnsPerCycle.Value);
		float num2 = (AllowRotation ? (phase * 360f * num) : 0f);
		float num3 = (Plugin.StretchEnabled ? stretch : 1f);
		bool worldSpace = Plugin.WorldSpace;
		Vector3 val = (worldSpace ? _root.TransformPoint(_localCenter) : _localCenter);
		Vector3 val2 = (worldSpace ? Plugin.AxisValue : Vector3.up);
		float num5;
		if (worldSpace)
		{
			float num4 = float.MaxValue;
			Vector3 val3 = default(Vector3);
			for (int i = 0; i < 8; i++)
			{
				((Vector3)(ref val3))..ctor(((i & 1) == 0) ? _localMin.x : _localMax.x, ((i & 2) == 0) ? _localMin.y : _localMax.y, ((i & 4) == 0) ? _localMin.z : _localMax.z);
				float y = _root.TransformPoint(val3).y;
				if (y < num4)
				{
					num4 = y;
				}
			}
			num5 = num4 - val.y;
		}
		else
		{
			num5 = _localMin.y - _localCenter.y;
		}
		Matrix4x4 val4 = Matrix4x4.Rotate(Quaternion.AngleAxis(num2, val2));
		Matrix4x4 val5 = Matrix4x4.Translate(val) * val4 * Matrix4x4.Translate(-val);
		Matrix4x4 val6 = Matrix4x4.Scale(new Vector3(1f, num3, 1f));
		Matrix4x4 val7 = Matrix4x4.Translate(val) * val6 * Matrix4x4.Translate(-val);
		return Matrix4x4.Translate(new Vector3(0f, num5 * (1f - num3), 0f)) * val7 * val5;
	}

	private void ApplyMatrix(Matrix4x4 t)
	{
		//IL_00b4: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: 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_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: 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_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: 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_015e: 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_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: 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_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: 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_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < _nodes.Count; i++)
		{
			VisualNode visualNode = _nodes[i];
			if ((Object)(object)visualNode.Node == (Object)null)
			{
				continue;
			}
			if ((Object)(object)visualNode.Source != (Object)null)
			{
				if ((Object)(object)visualNode.ProxyRenderer != (Object)null)
				{
					bool flag = (Object)(object)visualNode.Source != (Object)null && ((Component)visualNode.Source).gameObject.activeInHierarchy;
					if (visualNode.ProxyRenderer.enabled != flag)
					{
						visualNode.ProxyRenderer.enabled = flag;
					}
				}
				SetWorld(visualNode.Node, t * ((Component)visualNode.Source).transform.localToWorldMatrix);
				continue;
			}
			if (visualNode.HasApplied)
			{
				Vector3 val = visualNode.Node.localPosition - visualNode.LastPos;
				if (((Vector3)(ref val)).sqrMagnitude < 1E-08f && Quaternion.Angle(visualNode.Node.localRotation, visualNode.LastRot) < 0.05f)
				{
					val = visualNode.Node.localScale - visualNode.LastScale;
					if (((Vector3)(ref val)).sqrMagnitude < 1E-08f)
					{
						goto IL_012d;
					}
				}
			}
			visualNode.BaseLocal = LocalOf(visualNode.Node);
			goto IL_012d;
			IL_012d:
			Transform parent = visualNode.Parent;
			Matrix4x4 val2 = (((Object)(object)parent != (Object)null) ? (parent.localToWorldMatrix * visualNode.BaseLocal) : visualNode.BaseLocal);
			Matrix4x4 val3 = t * val2;
			Matrix4x4 m = (((Object)(object)parent != (Object)null) ? (parent.worldToLocalMatrix * val3) : val3);
			SetLocal(visualNode.Node, m, out var pos, out var rot, out var scale);
			visualNode.LastPos = pos;
			visualNode.LastRot = rot;
			visualNode.LastScale = scale;
			visualNode.HasApplied = true;
		}
	}

	private static void SetWorld(Transform t, Matrix4x4 world)
	{
		//IL_0017: 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)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		Matrix4x4 m = (((Object)(object)t.parent != (Object)null) ? (t.parent.worldToLocalMatrix * world) : world);
		SetLocal(t, m, out var _, out var _, out var _);
	}

	private static void SetLocal(Transform t, Matrix4x4 m, out Vector3 pos, out Quaternion rot, out Vector3 scale)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: 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)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: 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_00fc: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Vector4.op_Implicit(((Matrix4x4)(ref m)).GetColumn(0));
		Vector3 val2 = Vector4.op_Implicit(((Matrix4x4)(ref m)).GetColumn(1));
		Vector3 val3 = Vector4.op_Implicit(((Matrix4x4)(ref m)).GetColumn(2));
		scale = new Vector3(((Vector3)(ref val)).magnitude, ((Vector3)(ref val2)).magnitude, ((Vector3)(ref val3)).magnitude);
		if (Vector3.Dot(Vector3.Cross(val, val2), val3) < 0f)
		{
			scale.x = 0f - scale.x;
		}
		if (scale.x != 0f)
		{
			val /= Mathf.Abs(scale.x);
		}
		if (scale.y != 0f)
		{
			val2 /= Mathf.Abs(scale.y);
		}
		if (scale.z != 0f)
		{
			val3 /= Mathf.Abs(scale.z);
		}
		rot = ((((Vector3)(ref val3)).sqrMagnitude > 1E-08f && ((Vector3)(ref val2)).sqrMagnitude > 1E-08f) ? Quaternion.LookRotation(val3, val2) : Quaternion.identity);
		pos = Vector4.op_Implicit(((Matrix4x4)(ref m)).GetColumn(3));
		t.localPosition = pos;
		t.localRotation = rot;
		t.localScale = scale;
	}

	private void OnDestroy()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (_ready && (Object)(object)_root != (Object)null && _applied)
			{
				ApplyMatrix(Matrix4x4.identity);
			}
		}
		catch
		{
		}
		for (int i = 0; i < _hidden.Count; i++)
		{
			if ((Object)(object)_hidden[i] != (Object)null)
			{
				_hidden[i].enabled = true;
			}
		}
		for (int j = 0; j < _proxies.Count; j++)
		{
			if ((Object)(object)_proxies[j] != (Object)null)
			{
				Object.Destroy((Object)(object)_proxies[j]);
			}
		}
		_hidden.Clear();
		_proxies.Clear();
		_nodes.Clear();
		_ready = false;
	}
}
[BepInPlugin("com.peaks.jellyinteract", "A-Drink-with-Friends", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "com.peaks.jellyinteract";

	public static Plugin Instance;

	internal ManualLogSource Logger;

	private Harmony _harmony;

	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<KeyCode> ToggleKey;

	internal static ConfigEntry<KeyCode> PanelKey;

	internal static ConfigEntry<bool> EnableRotation;

	internal static ConfigEntry<bool> EnableStretch;

	internal static ConfigEntry<float> CycleSeconds;

	internal static ConfigEntry<float> StretchMultiplier;

	internal static ConfigEntry<float> RotationTurnsPerCycle;

	internal static ConfigEntry<float> StretchPerRotation;

	internal static ConfigEntry<string> AxisSpace;

	internal static ConfigEntry<string> RotationAxis;

	internal static ConfigEntry<bool> AffectItems;

	internal static ConfigEntry<bool> AffectCharacters;

	internal static ConfigEntry<bool> RotateCharacters;

	internal static ConfigEntry<bool> AffectLocalPlayer;

	internal static ConfigEntry<bool> AffectBots;

	internal static ConfigEntry<bool> AffectOtherInteractibles;

	internal static ConfigEntry<bool> AffectHeldItems;

	internal static ConfigEntry<string> ExcludeTypes;

	internal static ConfigEntry<string> ExcludeNames;

	internal static ConfigEntry<bool> ProtectColliders;

	internal static ConfigEntry<float> MaxDistance;

	internal static ConfigEntry<float> ScanInterval;

	internal static ConfigEntry<bool> Diagnose;

	internal static ConfigEntry<string> DiagnoseFilter;

	internal static ConfigEntry<string> MusicFolder;

	internal static ConfigEntry<bool> MusicEnabled;

	internal static ConfigEntry<bool> LoopMusic;

	internal static ConfigEntry<string> Preset1Name;

	internal static ConfigEntry<string> Preset1File;

	internal static ConfigEntry<float> Preset1Cycle;

	internal static ConfigEntry<float> Preset1Stretch;

	internal static ConfigEntry<string> Preset2Name;

	internal static ConfigEntry<string> Preset2File;

	internal static ConfigEntry<float> Preset2Cycle;

	internal static ConfigEntry<float> Preset2Stretch;

	internal static bool Animating;

	internal static bool RotationEnabled = true;

	internal static bool StretchEnabled = true;

	internal static bool WorldSpace = true;

	internal static float PhaseValue;

	internal static float StretchValue = 1f;

	internal static Vector3 AxisValue = Vector3.up;

	internal static bool PanelVisible;

	private const float BaseAmplitude = 0.15f;

	private float _phase;

	private float _scanTimer;

	private int _diagnoseBudget;

	private Rect _panelRect = new Rect(120f, 120f, 430f, 470f);

	private GUIStyle _bgStyle;

	private GUIStyle _btnStyle;

	private GUIStyle _lblStyle;

	private GUIStyle _titleStyle;

	private GUIStyle _hintStyle;

	private GUIStyle _fieldStyle;

	private Texture2D _texBg;

	private Texture2D _texBtn;

	private Texture2D _texBtnHover;

	private bool _stylesReady;

	private string _speedText;

	private float _speedTextFor = float.NaN;

	private AudioSource _audio;

	private Coroutine _musicRoutine;

	private bool _wasInLevel;

	private static bool IsChinese
	{
		get
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			try
			{
				Language cURRENT_LANGUAGE = LocalizedText.CURRENT_LANGUAGE;
				return (int)cURRENT_LANGUAGE == 9 || (int)cURRENT_LANGUAGE == 10;
			}
			catch
			{
				return false;
			}
		}
	}

	private void Awake()
	{
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Expected O, but got Unknown
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Expected O, but got Unknown
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Expected O, but got Unknown
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Expected O, but got Unknown
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: Expected O, but got Unknown
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Expected O, but got Unknown
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Expected O, but got Unknown
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Expected O, but got Unknown
		//IL_0472: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Expected O, but got Unknown
		//IL_04af: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b9: Expected O, but got Unknown
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1.General", "Enabled", true, "总开关:开启后所有可交互模型的旋转 / 伸缩生效。");
		ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1.General", "ToggleKey", (KeyCode)111, "游戏内快速切换总开关的按键。");
		PanelKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1.General", "PanelKey", (KeyCode)288, "打开 / 关闭测试面板的按键。");
		PanelVisible = ((BaseUnityPlugin)this).Config.Bind<bool>("1.General", "OpenPanelOnStart", false, "启动时直接打开测试面板(游戏内也可以按 PanelKey 打开)。").Value;
		_harmony = new Harmony("com.peaks.jellyinteract");
		try
		{
			_harmony.PatchAll(typeof(CursorPatcher));
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("[Jelly] cursor patch failed: " + ex.Message));
		}
		GameObject val = new GameObject("JellyInteractMusic");
		Object.DontDestroyOnLoad((Object)(object)val);
		_audio = val.AddComponent<AudioSource>();
		_audio.playOnAwake = false;
		_audio.loop = false;
		_audio.volume = 0.7f;
		EnableRotation = ((BaseUnityPlugin)this).Config.Bind<bool>("2.Animation", "EnableRotation", true, "是否旋转。");
		EnableStretch = ((BaseUnityPlugin)this).Config.Bind<bool>("2.Animation", "EnableStretch", true, "是否伸缩。");
		CycleSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("2.Animation", "CycleSeconds", 2f, new ConfigDescription("旋转与伸缩共用一个速度:这就是「转一圈 + 伸缩一次」所需的秒数,越小越快。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 60f), Array.Empty<object>()));
		StretchMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("2.Animation", "StretchMultiplier", 1f, new ConfigDescription("伸缩倍率:1 = 高度在 ±15% 之间弹,倍率越高幅度越大。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
		RotationTurnsPerCycle = ((BaseUnityPlugin)this).Config.Bind<float>("2.Animation", "RotationTurnsPerCycle", 1f, new ConfigDescription("每个周期旋转多少圈。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), Array.Empty<object>()));
		StretchPerRotation = ((BaseUnityPlugin)this).Config.Bind<float>("2.Animation", "StretchPerRotation", 1f, new ConfigDescription("每个周期做几次伸缩。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), Array.Empty<object>()));
		AxisSpace = ((BaseUnityPlugin)this).Config.Bind<string>("2.Animation", "AxisSpace", "World", new ConfigDescription("旋转/拉伸的参考系。World = 绕世界竖直轴原地自转、沿世界竖直方向上下弹(推荐,物体在地上翻滚过也不会变成横着转);Local = 绕模型自身的竖直轴。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "World", "Local" }), Array.Empty<object>()));
		RotationAxis = ((BaseUnityPlugin)this).Config.Bind<string>("2.Animation", "RotationAxis", "Y", new ConfigDescription("旋转轴(仅 AxisSpace=World 时有效):Y = 绕竖直轴自转,X / Z = 翻滚,XY = 斜轴。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Y", "X", "Z", "XY" }), Array.Empty<object>()));
		AffectItems = ((BaseUnityPlugin)this).Config.Bind<bool>("3.Scope", "AffectItems", true, "让道具(Item)动起来。");
		AffectCharacters = ((BaseUnityPlugin)this).Config.Bind<bool>("3.Scope", "AffectCharacters", true, "让其他玩家的角色模型参与。关闭后角色完全不动;开启后角色默认【只伸缩、不旋转】(旋转会连带骨骼上的碰撞体和手持物,观感也很诡异)。");
		RotateCharacters = ((BaseUnityPlugin)this).Config.Bind<bool>("3.Scope", "RotateCharacters", false, "角色是否也要旋转。默认关闭:角色只做上下 Q 弹伸缩。开启后角色会和道具一样自转,注意这会影响角色身上的碰撞体。");
		AffectLocalPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("3.Scope", "AffectLocalPlayer", false, "让本地玩家自己的模型也动。【强烈建议保持关闭】本地玩家的模型和第一人称摄像机绑在一起,旋转模型会把视角一起转走,导致完全没法正常行走。");
		AffectBots = ((BaseUnityPlugin)this).Config.Bind<bool>("3.Scope", "AffectBots", false, "是否也旋转 AI 角色(蘑菇僵尸、童军领队迈尔斯等)。【建议保持关闭】它们的骨骼上挂着碰撞体,旋转会连带移动碰撞体,导致它们走路、攻击、寻路全部异常。");
		AffectOtherInteractibles = ((BaseUnityPlugin)this).Config.Bind<bool>("3.Scope", "AffectOtherInteractibles", true, "让其余可交互物动起来(篝火、行李等)。");
		AffectHeldItems = ((BaseUnityPlugin)this).Config.Bind<bool>("3.Scope", "AffectHeldItems", false, "手持 / 背包里的道具是否还要【单独】旋转拉伸。推荐关闭:它们的坐标本来就被游戏每帧绑在角色身上,关闭后会跟着角色一起动。");
		ExcludeTypes = ((BaseUnityPlugin)this).Config.Bind<string>("3.Scope", "ExcludeTypes", "RopeSegment,JungleVine,ClimbHandle,TriggerOnInteract,Scoutmaster", "按【组件类型名】排除,逗号分隔,包含匹配。会同时比对可交互组件本身和对象上挂着的其它组件。默认排除:可攀爬可通行的机关(绳索 / 藤蔓 / 攀爬把手 / 交互触发器),以及童军领队 Scoutmaster。注意这里不再排除背包,否则火箭背包就不会动了。");
		ExcludeNames = ((BaseUnityPlugin)this).Config.Bind<string>("3.Scope", "ExcludeNames", "Bridge,Clock,Tower,Bot Character,BingBong,Frog,EarlyBird,Early Bird,Snowball,Rock,Stone,ScoutsHonor,BookOfBones", "按【对象名】排除,逗号分隔,【词边界前缀匹配】。默认排除桥、钟塔这类大型结构,全部 AI 角色(Bot Character),宾邦、青蛙、早起虫儿、雪球、石头、童军的荣耀,以及骸骨之书 BookOfBones。");
		ProtectColliders = ((BaseUnityPlugin)this).Config.Bind<bool>("4.Safety", "ProtectColliders", true, "物理保护:只要节点的子树里存在碰撞体,就改用代理渲染器(或放弃该节点),保证碰撞体绝不会被移动或缩放。强烈建议保持开启。");
		MaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("4.Safety", "MaxDistance", 0f, new ConfigDescription("只处理离玩家这个距离以内的可交互物;0 = 不限距离(默认,全局生效)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>()));
		ScanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("4.Safety", "ScanInterval", 2f, new ConfigDescription("扫描场景中可交互物的间隔秒数。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 30f), Array.Empty<object>()));
		Diagnose = ((BaseUnityPlugin)this).Config.Bind<bool>("5.Debug", "Diagnose", false, "把每个可交互物的渲染节点结构写进 BepInEx 日志(排查用)。");
		DiagnoseFilter = ((BaseUnityPlugin)this).Config.Bind<string>("5.Debug", "DiagnoseFilter", "", "诊断输出过滤:只打印对象名以它开头的条目(例如 Rocket / Scout)。留空则打印全部,但受条数上限限制;填了过滤词就不受上限限制。");
		MusicFolder = ((BaseUnityPlugin)this).Config.Bind<string>("6.Music", "MusicFolder", "", "音乐文件夹路径。留空 = 使用插件目录下的 music 文件夹(推荐,随 mod 一起分发)。");
		LoopMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("6.Music", "LoopMusic", false, "播放一遍后是否循环。默认关闭:放完就停。");
		MusicEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("6.Music", "MusicEnabled", true, "音乐总开关。关掉会立刻停止正在播放的音乐,并且按预设时只改参数不放歌。");
		Preset1Name = ((BaseUnityPlugin)this).Config.Bind<string>("6.Music", "Preset1Name", "朋友的酒", "第一个预设按钮上显示的名字(只影响面板上显示的文字)。");
		Preset1File = ((BaseUnityPlugin)this).Config.Bind<string>("6.Music", "Preset1File", "A Drink with Friends.mp3", "第一个预设播放的文件名(放在音乐文件夹里)。用纯英文名可以避开中文路径的编码问题。");
		Preset1Cycle = ((BaseUnityPlugin)this).Config.Bind<float>("6.Music", "Preset1Cycle", 0.463f, "第一个预设的一圈秒数。");
		Preset1Stretch = ((BaseUnityPlugin)this).Config.Bind<float>("6.Music", "Preset1Stretch", 2.5f, "第一个预设的伸缩倍率。");
		Preset2Name = ((BaseUnityPlugin)this).Config.Bind<string>("6.Music", "Preset2Name", "Funky Town", "第二个预设按钮上显示的名字。");
		Preset2File = ((BaseUnityPlugin)this).Config.Bind<string>("6.Music", "Preset2File", "Funky Town .mp3", "第二个预设播放的文件名(放在音乐文件夹里)。");
		Preset2Cycle = ((BaseUnityPlugin)this).Config.Bind<float>("6.Music", "Preset2Cycle", 1f, "第二个预设的一圈秒数。");
		Preset2Stretch = ((BaseUnityPlugin)this).Config.Bind<float>("6.Music", "Preset2Stretch", 1.5f, "第二个预设的伸缩倍率。");
		Logger.LogInfo((object)"[Jelly] JellyInteract v1.5.6 loaded  (P Y D J = 测试面板)");
	}

	private void Update()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		if (Input.GetKeyDown(PanelKey.Value))
		{
			PanelVisible = !PanelVisible;
			Logger.LogInfo((object)("[Jelly] panel " + (PanelVisible ? "open" : "closed")));
		}
		if (Input.GetKeyDown(ToggleKey.Value))
		{
			Enabled.Value = !Enabled.Value;
			Logger.LogInfo((object)("[Jelly] " + (Enabled.Value ? "ON" : "OFF")));
		}
		bool flag = (Object)(object)Character.localCharacter != (Object)null;
		if (_wasInLevel && !flag && (Object)(object)_audio != (Object)null && _audio.isPlaying)
		{
			StopMusic();
			Logger.LogInfo((object)"[Jelly] left the level, music stopped");
		}
		_wasInLevel = flag;
		RotationEnabled = EnableRotation.Value;
		StretchEnabled = EnableStretch.Value;
		WorldSpace = !string.Equals(AxisSpace.Value, "Local", StringComparison.OrdinalIgnoreCase);
		if (Enabled.Value)
		{
			float num = Mathf.Clamp(CycleSeconds.Value, 0.05f, 600f);
			_phase += Time.deltaTime / num;
			if (_phase > 1000000f)
			{
				_phase = 0f;
			}
			float num2 = Mathf.Clamp(0.15f * Mathf.Max(0f, StretchMultiplier.Value), 0f, 0.9f);
			float num3 = Mathf.Max(0.05f, StretchPerRotation.Value);
			PhaseValue = _phase;
			StretchValue = 1f + num2 * Mathf.Sin(_phase * 2f * (float)Math.PI * num3);
			AxisValue = ParseAxis(RotationAxis.Value);
			Animating = true;
		}
		else
		{
			Animating = false;
		}
		_scanTimer += Time.deltaTime;
		if (_scanTimer >= Mathf.Max(0.25f, ScanInterval.Value))
		{
			_scanTimer = 0f;
			if (Enabled.Value)
			{
				Scan();
			}
		}
	}

	private static Vector3 ParseAxis(string s)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(s))
		{
			return Vector3.up;
		}
		switch (s.Trim().ToUpperInvariant())
		{
		case "X":
			return Vector3.right;
		case "Z":
			return Vector3.forward;
		case "XY":
		{
			Vector3 val = new Vector3(1f, 1f, 0f);
			return ((Vector3)(ref val)).normalized;
		}
		default:
			return Vector3.up;
		}
	}

	private void Scan()
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)Character.localCharacter))
		{
			return;
		}
		MonoBehaviour[] array;
		try
		{
			array = Object.FindObjectsByType<MonoBehaviour>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("[Jelly] scan failed: " + ex.Message));
			return;
		}
		Camera main = Camera.main;
		Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.position : ((Component)Character.localCharacter).transform.position);
		float value = MaxDistance.Value;
		float num = ((value > 0f) ? (value * value) : 0f);
		List<string> types = ParseList(ExcludeTypes.Value);
		List<string> names = ParseList(ExcludeNames.Value);
		List<MonoBehaviour> list = new List<MonoBehaviour>(64);
		int num2 = 0;
		foreach (MonoBehaviour val2 in array)
		{
			if ((Object)(object)val2 == (Object)null || val2 is JellyAnimator || !(val2 is IInteractible))
			{
				continue;
			}
			GameObject gameObject = ((Component)val2).gameObject;
			string text = null;
			if (!ShouldAffect(val2))
			{
				text = "scope";
			}
			else if (IsExcludedType(val2, types))
			{
				text = "type";
			}
			else if (IsExcludedName(((Object)gameObject).name, names))
			{
				text = "name";
			}
			else if (IsUnderLocalPlayer(gameObject.transform))
			{
				text = "localplayer";
			}
			if (text != null)
			{
				if (DropAnimator(gameObject))
				{
					num2++;
				}
				LogDiagnose("SKIP " + ((Object)gameObject).name + " :: " + ((object)val2).GetType().Name + " reason=" + text);
				continue;
			}
			if (num > 0f)
			{
				Vector3 val3 = gameObject.transform.position - val;
				if (((Vector3)(ref val3)).sqrMagnitude > num)
				{
					if (DropAnimator(gameObject))
					{
						num2++;
					}
					LogDiagnose("SKIP " + ((Object)gameObject).name + " :: out of range");
					continue;
				}
			}
			list.Add(val2);
		}
		list.Sort((MonoBehaviour a, MonoBehaviour b) => HierarchyDepth(((Component)a).transform).CompareTo(HierarchyDepth(((Component)b).transform)));
		int num3 = 0;
		int num4 = 0;
		foreach (MonoBehaviour item in list)
		{
			GameObject gameObject2 = ((Component)item).gameObject;
			JellyAnimator component = gameObject2.GetComponent<JellyAnimator>();
			JellyAnimator jellyAnimator = FindAncestorAnimator(gameObject2.transform.parent);
			if ((Object)(object)component != (Object)null)
			{
				if ((Object)(object)jellyAnimator != (Object)null)
				{
					Object.Destroy((Object)(object)component);
					num2++;
				}
				continue;
			}
			if (!(item is BackpackOnBackVisuals) && (Object)(object)jellyAnimator != (Object)null)
			{
				num4++;
				LogDiagnose("FOLLOW " + ((Object)gameObject2).name + " :: " + ((object)item).GetType().Name + " follows parent");
				continue;
			}
			JellyAnimator jellyAnimator2 = gameObject2.AddComponent<JellyAnimator>();
			if (jellyAnimator2.Build(item))
			{
				num3++;
				JellyAnimator[] componentsInChildren = gameObject2.GetComponentsInChildren<JellyAnimator>(true);
				foreach (JellyAnimator jellyAnimator3 in componentsInChildren)
				{
					if ((Object)(object)jellyAnimator3 != (Object)null && (Object)(object)jellyAnimator3 != (Object)(object)jellyAnimator2)
					{
						Object.Destroy((Object)(object)jellyAnimator3);
					}
				}
				LogDiagnose(((Object)gameObject2).name + " :: " + jellyAnimator2.Report);
			}
			else
			{
				Object.Destroy((Object)(object)jellyAnimator2);
			}
		}
		if (num3 > 0 || num4 > 0 || num2 > 0)
		{
			Logger.LogInfo((object)$"[Jelly] scan: {list.Count} targets ({array.Length} behaviours), {num3} new, {num4} follow parent, {num2} dropped");
		}
	}

	private static bool DropAnimator(GameObject go)
	{
		JellyAnimator component = go.GetComponent<JellyAnimator>();
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		Object.Destroy((Object)(object)component);
		return true;
	}

	private void LogDiagnose(string msg)
	{
		if (!Diagnose.Value)
		{
			return;
		}
		string value = DiagnoseFilter.Value;
		if (!string.IsNullOrEmpty(value))
		{
			bool flag = false;
			string[] array = value.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0 && msg.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return;
			}
		}
		else if (_diagnoseBudget >= 400)
		{
			return;
		}
		_diagnoseBudget++;
		Logger.LogInfo((object)("[Jelly] " + msg));
	}

	private static List<string> ParseList(string raw)
	{
		if (string.IsNullOrWhiteSpace(raw))
		{
			return null;
		}
		List<string> list = new List<string>();
		string[] array = raw.Split(new char[1] { ',' });
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length > 0)
			{
				list.Add(text);
			}
		}
		if (list.Count <= 0)
		{
			return null;
		}
		return list;
	}

	private static bool IsExcludedType(MonoBehaviour mb, List<string> types)
	{
		if (types == null)
		{
			return false;
		}
		if (MatchesAny(((object)mb).GetType().Name, types))
		{
			return true;
		}
		Component[] components = ((Component)mb).gameObject.GetComponents<Component>();
		for (int i = 0; i < components.Length; i++)
		{
			if (!((Object)(object)components[i] == (Object)null) && MatchesAny(((object)components[i]).GetType().Name, types))
			{
				return true;
			}
		}
		return false;
	}

	private static bool MatchesAny(string name, List<string> keys)
	{
		if (string.IsNullOrEmpty(name) || keys == null)
		{
			return false;
		}
		for (int i = 0; i < keys.Count; i++)
		{
			if (name.IndexOf(keys[i], StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsExcludedName(string name, List<string> names)
	{
		if (names == null || string.IsNullOrEmpty(name))
		{
			return false;
		}
		for (int i = 0; i < names.Count; i++)
		{
			string text = names[i];
			if (text.Length == 0)
			{
				continue;
			}
			if (name.Equals(text, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (name.Length > text.Length && name.StartsWith(text, StringComparison.OrdinalIgnoreCase))
			{
				char c = name[text.Length];
				if (c == ' ' || c == '(' || c == '_' || c == '-' || c == '.')
				{
					return true;
				}
			}
		}
		return false;
	}

	private static int HierarchyDepth(Transform t)
	{
		int num = 0;
		while ((Object)(object)t.parent != (Object)null)
		{
			num++;
			t = t.parent;
		}
		return num;
	}

	private static JellyAnimator FindAncestorAnimator(Transform t)
	{
		int num = 0;
		while ((Object)(object)t != (Object)null && num++ < 64)
		{
			JellyAnimator component = ((Component)t).GetComponent<JellyAnimator>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			t = t.parent;
		}
		return null;
	}

	private static bool IsUnderLocalPlayer(Transform t)
	{
		try
		{
			Character componentInParent = ((Component)t).GetComponentInParent<Character>(true);
			return (Object)(object)componentInParent != (Object)null && componentInParent.IsLocal;
		}
		catch
		{
			return false;
		}
	}

	internal static bool ShouldAffect(MonoBehaviour mb)
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)mb == (Object)null)
		{
			return false;
		}
		CharacterInteractible val = (CharacterInteractible)(object)((mb is CharacterInteractible) ? mb : null);
		if (val != null)
		{
			if (!AffectCharacters.Value)
			{
				return false;
			}
			Character val2 = (((Object)(object)val.character != (Object)null) ? val.character : ((Component)val).GetComponent<Character>());
			if ((Object)(object)val2 != (Object)null)
			{
				if (val2.IsLocal && !AffectLocalPlayer.Value)
				{
					return false;
				}
				if (val2.isBot && !AffectBots.Value)
				{
					return false;
				}
			}
			return true;
		}
		Item val3 = (Item)(object)((mb is Item) ? mb : null);
		if (val3 != null)
		{
			if (!AffectItems.Value)
			{
				return false;
			}
			if (!AffectHeldItems.Value && (int)val3.itemState != 0)
			{
				return false;
			}
			return true;
		}
		return AffectOtherInteractibles.Value;
	}

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

	private void ApplyPreset(string label, string file, float cycle, float stretch)
	{
		CycleSeconds.Value = Mathf.Clamp(cycle, 0.1f, 60f);
		StretchMultiplier.Value = Mathf.Clamp(stretch, 0f, 3f);
		_speedText = CycleSeconds.Value.ToString("F2", CultureInfo.InvariantCulture);
		_speedTextFor = CycleSeconds.Value;
		Logger.LogInfo((object)$"[Jelly] preset [{label}] -> cycle={CycleSeconds.Value:F3}s stretch=x{StretchMultiplier.Value:F2}");
		PlayMusic(file);
	}

	private void PlayMusic(string file)
	{
		if (!((Object)(object)_audio == (Object)null))
		{
			if (_musicRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_musicRoutine);
				_musicRoutine = null;
			}
			_audio.Stop();
			_audio.clip = null;
			if (!MusicEnabled.Value)
			{
				Logger.LogInfo((object)"[Jelly] music is off, preset only changed the parameters");
			}
			else
			{
				_musicRoutine = ((MonoBehaviour)this).StartCoroutine(LoadAndPlay(file));
			}
		}
	}

	private void StopMusic()
	{
		if (_musicRoutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(_musicRoutine);
			_musicRoutine = null;
		}
		if ((Object)(object)_audio != (Object)null)
		{
			_audio.Stop();
			_audio.clip = null;
		}
	}

	private IEnumerator LoadAndPlay(string file)
	{
		string path = ResolveMusicPath(file);
		if (path == null)
		{
			Logger.LogWarning((object)("[Jelly] music not found: " + file + " (folder=" + MusicFolder.Value + ")"));
			yield break;
		}
		AudioClip clip = null;
		yield return LoadClip(path, delegate(AudioClip c)
		{
			clip = c;
		});
		if ((Object)(object)clip == (Object)null)
		{
			string text;
			try
			{
				text = Path.Combine(Path.GetTempPath(), "jellyinteract_music" + Path.GetExtension(path));
				File.Copy(path, text, overwrite: true);
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[Jelly] temp copy failed: " + ex.Message));
				text = null;
			}
			if (text != null)
			{
				Logger.LogInfo((object)("[Jelly] retrying via temp path: " + text));
				yield return LoadClip(text, delegate(AudioClip c)
				{
					clip = c;
				});
			}
		}
		if ((Object)(object)clip == (Object)null)
		{
			Logger.LogWarning((object)("[Jelly] music could not be decoded: " + file));
			yield break;
		}
		_audio.Stop();
		_audio.clip = clip;
		_audio.loop = LoopMusic.Value;
		_audio.Play();
		Logger.LogInfo((object)$"[Jelly] playing {file} ({clip.length:F1}s, loop={_audio.loop})");
	}

	private IEnumerator LoadClip(string path, Action<AudioClip> done)
	{
		string url;
		try
		{
			url = new Uri(path).AbsoluteUri;
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("[Jelly] bad music path: " + ex.Message));
			done(null);
			yield break;
		}
		UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)13);
		try
		{
			yield return req.SendWebRequest();
			if ((int)req.result != 1)
			{
				Logger.LogWarning((object)("[Jelly] music load failed: " + req.error + "  (" + url + ")"));
				done(null);
				yield break;
			}
			AudioClip obj = null;
			try
			{
				obj = DownloadHandlerAudioClip.GetContent(req);
			}
			catch (Exception ex2)
			{
				Logger.LogWarning((object)("[Jelly] music decode failed: " + ex2.Message));
			}
			done(obj);
		}
		finally
		{
			((IDisposable)req)?.Dispose();
		}
	}

	private static string ResolveMusicPath(string file)
	{
		if (string.IsNullOrEmpty(file))
		{
			return null;
		}
		string value = MusicFolder.Value;
		if (!string.IsNullOrEmpty(value))
		{
			try
			{
				string text = Path.Combine(value, file);
				if (File.Exists(text))
				{
					return text;
				}
			}
			catch
			{
			}
		}
		try
		{
			string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
			if (!string.IsNullOrEmpty(directoryName))
			{
				string text2 = Path.Combine(directoryName, "music", file);
				if (File.Exists(text2))
				{
					return text2;
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private static string L(string zh, string en)
	{
		if (!IsChinese)
		{
			return en;
		}
		return zh;
	}

	private void OnGUI()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		if (PanelVisible)
		{
			InitStyles();
			_panelRect = GUILayout.Window(20180316, _panelRect, new WindowFunction(DrawPanel), L("A-Drink-with-Friends 测试面板", "A-Drink-with-Friends"), _bgStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(430f) });
		}
	}

	private void DrawPanel(int id)
	{
		//IL_0029: 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_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.Space(4f);
		GUILayout.Label("A-Drink-with-Friends", _titleStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Label(L($"按 {PanelKey.Value} 开关本面板 · {ToggleKey.Value} 切换总开关", $"{PanelKey.Value} toggles this panel · {ToggleKey.Value} toggles the mod"), _hintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(10f);
		bool flag = ToggleRow(L("总开关", "Master switch"), Enabled.Value);
		if (flag != Enabled.Value)
		{
			Enabled.Value = flag;
		}
		bool flag2 = ToggleRow(L("旋转", "Rotation"), EnableRotation.Value);
		if (flag2 != EnableRotation.Value)
		{
			EnableRotation.Value = flag2;
		}
		bool flag3 = ToggleRow(L("伸缩", "Stretch"), EnableStretch.Value);
		if (flag3 != EnableStretch.Value)
		{
			EnableStretch.Value = flag3;
		}
		bool flag4 = ToggleRow(L("其他玩家角色", "Other players"), AffectCharacters.Value);
		if (flag4 != AffectCharacters.Value)
		{
			AffectCharacters.Value = flag4;
		}
		GUILayout.Space(6f);
		float num = SliderWithInput(L("一圈秒数(速度)", "Seconds per cycle"), CycleSeconds.Value, 0.1f, 60f, ref _speedText, ref _speedTextFor);
		if (Mathf.Abs(num - CycleSeconds.Value) > 0.0001f)
		{
			CycleSeconds.Value = num;
		}
		float num2 = SliderRow(L("伸缩倍率", "Stretch multiplier"), StretchMultiplier.Value, 0f, 3f, "x{0:F2}");
		if (Mathf.Abs(num2 - StretchMultiplier.Value) > 0.0001f)
		{
			StretchMultiplier.Value = num2;
		}
		float num3 = SliderRow(L("每周期圈数", "Turns per cycle"), RotationTurnsPerCycle.Value, 0.25f, 4f, "{0:F2}");
		if (Mathf.Abs(num3 - RotationTurnsPerCycle.Value) > 0.0001f)
		{
			RotationTurnsPerCycle.Value = num3;
		}
		GUILayout.Space(6f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(L("旋转轴", "Rotation axis"), _lblStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(175f) });
		if (GUILayout.Button(RotationAxis.Value, _btnStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
		{
			RotationAxis.Value = NextAxis(RotationAxis.Value);
		}
		GUILayout.Label(L($"当前幅度 ±{0.15f * StretchMultiplier.Value * 100f:F1}%", $"Amplitude ±{0.15f * StretchMultiplier.Value * 100f:F1}%"), _lblStyle, Array.Empty<GUILayoutOption>());
		GUILayout.EndHorizontal();
		GUILayout.Space(10f);
		GUILayout.Label(L("预设(一键改参数 + 放歌)", "Presets (apply settings + play music)"), _hintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button(Preset1Name.Value, _btnStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
		{
			ApplyPreset(Preset1Name.Value, Preset1File.Value, Preset1Cycle.Value, Preset1Stretch.Value);
		}
		if (GUILayout.Button(Preset2Name.Value, _btnStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
		{
			ApplyPreset(Preset2Name.Value, Preset2File.Value, Preset2Cycle.Value, Preset2Stretch.Value);
		}
		GUILayout.EndHorizontal();
		bool flag5 = ToggleRow(L("音乐", "Music"), MusicEnabled.Value);
		if (flag5 != MusicEnabled.Value)
		{
			MusicEnabled.Value = flag5;
			if (!flag5)
			{
				StopMusic();
			}
			Logger.LogInfo((object)("[Jelly] music " + (flag5 ? "ON" : "OFF")));
		}
		bool flag6 = ToggleRow(L("循环音乐", "Loop music"), LoopMusic.Value);
		if (flag6 != LoopMusic.Value)
		{
			LoopMusic.Value = flag6;
			if ((Object)(object)_audio != (Object)null)
			{
				_audio.loop = flag6;
			}
		}
		GUILayout.Space(10f);
		GUILayout.Label(L("本地玩家不会旋转(模型和摄像机绑定)", "The local player is never animated (model is bound to the camera)"), _hintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(8f);
		GUILayout.Label(L("以下的实体与名字因不知名原因动画异常,加入黑名单:", "The following types and names glitch out for unknown reasons; they are blacklisted:"), _hintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Label(L("类型:" + ExcludeTypes.Value, "Types: " + ExcludeTypes.Value), _hintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Label(L("名字:" + ExcludeNames.Value, "Names: " + ExcludeNames.Value), _hintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(10f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.FlexibleSpace();
		if (GUILayout.Button(L("关闭", "Close"), _btnStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
		{
			PanelVisible = false;
		}
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();
		GUI.DragWindow();
	}

	private static string NextAxis(string cur)
	{
		return (cur ?? "Y").Trim().ToUpperInvariant() switch
		{
			"Y" => "X", 
			"X" => "Z", 
			"Z" => "XY", 
			_ => "Y", 
		};
	}

	private bool ToggleRow(string label, bool value)
	{
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(label, _lblStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(175f) });
		if (GUILayout.Button(value ? L("开", "ON") : L("关", "OFF"), _btnStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
		{
			value = !value;
		}
		GUILayout.EndHorizontal();
		return value;
	}

	private float SliderRow(string label, float value, float min, float max, string fmt)
	{
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(label, _lblStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(175f) });
		float num = GUILayout.HorizontalSlider(value, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) });
		GUILayout.Label(string.Format(fmt, num), _lblStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
		GUILayout.EndHorizontal();
		return num;
	}

	private float SliderWithInput(string label, float value, float min, float max, ref string cache, ref float cacheFor)
	{
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(label, _lblStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(175f) });
		float num = value;
		float num2 = GUILayout.HorizontalSlider(value, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) });
		if (Mathf.Abs(num2 - value) > 1E-05f)
		{
			num = num2;
			cache = num2.ToString("F2", CultureInfo.InvariantCulture);
			cacheFor = num;
		}
		if (string.IsNullOrEmpty(cache) || Mathf.Abs(cacheFor - value) > 0.0001f)
		{
			cache = value.ToString("F2", CultureInfo.InvariantCulture);
			cacheFor = value;
		}
		string text = GUILayout.TextField(cache, _fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(62f) });
		if (text != cache)
		{
			cache = text;
			if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				num = (cacheFor = Mathf.Clamp(result, min, max));
			}
		}
		GUILayout.EndHorizontal();
		return num;
	}

	private void InitStyles()
	{
		//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_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Expected O, but got Unknown
		//IL_00d7: Expected O, but got Unknown
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: 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_0125: 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_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: 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_017f: Expected O, but got Unknown
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: 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_01a3: Expected O, but got Unknown
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Expected O, but got Unknown
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Expected O, but got Unknown
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Expected O, but got Unknown
		if ((Object)(object)_texBg == (Object)null || (Object)(object)_texBtn == (Object)null)
		{
			_stylesReady = false;
		}
		if (!_stylesReady)
		{
			_stylesReady = true;
			Color textColor = H2C("1B5E20");
			_texBg = MakeTex(_texBg, H2C("DFFFE4"));
			_texBtn = MakeTex(_texBtn, Color.white);
			_texBtnHover = MakeTex(_texBtnHover, H2C("E8FFE8"));
			GUIStyle val = new GUIStyle(GUI.skin.box);
			val.normal.background = _texBg;
			val.normal.textColor = textColor;
			val.fontSize = 14;
			val.padding = new RectOffset(12, 12, 10, 10);
			_bgStyle = val;
			GUIStyle val2 = new GUIStyle(GUI.skin.button);
			val2.normal.background = _texBtn;
			val2.normal.textColor = Color.black;
			val2.hover.background = _texBtnHover;
			val2.hover.textColor = textColor;
			val2.active.background = _texBtnHover;
			val2.active.textColor = Color.black;
			val2.focused.background = _texBtn;
			val2.focused.textColor = Color.black;
			val2.fontSize = 13;
			val2.fixedHeight = 26f;
			_btnStyle = val2;
			_fieldStyle = new GUIStyle(GUI.skin.textField)
			{
				fontSize = 12,
				alignment = (TextAnchor)4
			};
			GUIStyle val3 = new GUIStyle(GUI.skin.label);
			val3.normal.textColor = textColor;
			val3.fontSize = 12;
			val3.alignment = (TextAnchor)3;
			_lblStyle = val3;
			GUIStyle val4 = new GUIStyle(GUI.skin.label);
			val4.normal.textColor = textColor;
			val4.fontSize = 17;
			val4.fontStyle = (FontStyle)1;
			val4.alignment = (TextAnchor)4;
			_titleStyle = val4;
			GUIStyle val5 = new GUIStyle(GUI.skin.label);
			val5.normal.textColor = H2C("4E6B52");
			val5.fontSize = 11;
			val5.wordWrap = true;
			_hintStyle = val5;
		}
	}

	private static Texture2D MakeTex(Texture2D old, Color c)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: 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_002b: Expected O, but got Unknown
		//IL_002c: Expected O, but got Unknown
		if ((Object)(object)old != (Object)null)
		{
			Object.Destroy((Object)(object)old);
		}
		Texture2D val = new Texture2D(1, 1);
		val.SetPixel(0, 0, c);
		val.Apply();
		Object.DontDestroyOnLoad((Object)val);
		return val;
	}

	private static Color H2C(string h)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		if (h[0] == '#')
		{
			h = h.Substring(1);
		}
		return new Color((float)Convert.ToInt32(h.Substring(0, 2), 16) / 255f, (float)Convert.ToInt32(h.Substring(2, 2), 16) / 255f, (float)Convert.ToInt32(h.Substring(4, 2), 16) / 255f, 1f);
	}
}
[HarmonyPatch(typeof(CursorHandler), "Update")]
internal static class CursorPatcher
{
	[HarmonyPrefix]
	private static bool Prefix()
	{
		if (!Plugin.PanelVisible)
		{
			return true;
		}
		Cursor.visible = true;
		Cursor.lockState = (CursorLockMode)0;
		return false;
	}
}