Decompiled source of PingPointUseItem v2.6.14

PingPointUseItem.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("PingPointUseItem")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PingPointUseItem")]
[assembly: AssemblyTitle("PingPointUseItem")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PingPointUseItem;

[BepInPlugin("rua.PingPointUseItem", "Ping Point Use Item", "2.6.14")]
public sealed class Plugin : BaseUnityPlugin
{
	private enum CollisionKind
	{
		None,
		Breakable,
		ShelfShroom,
		WarpOnThrow,
		HealingPuffShroom
	}

	private struct FrisbeePingSnapshot
	{
		public readonly Vector3 Point;

		public readonly Vector3 Normal;

		public readonly Collider Collider;

		public FrisbeePingSnapshot(Vector3 point, Vector3 normal, Collider collider)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_0009: Unknown result type (might be due to invalid IL or missing references)
			Point = point;
			Normal = normal;
			Collider = collider;
		}
	}

	private struct FrisbeeTarget
	{
		public readonly Collider Collider;

		public readonly float DistanceSquared;

		public readonly int Identity;

		public readonly string TargetType;

		public readonly string DisplayName;

		public readonly bool IsNonPlayer;

		public FrisbeeTarget(Collider collider, float distanceSquared, int identity, string targetType, string displayName, bool isNonPlayer)
		{
			Collider = collider;
			DistanceSquared = distanceSquared;
			Identity = identity;
			TargetType = targetType;
			DisplayName = displayName;
			IsNonPlayer = isNonPlayer;
		}
	}

	private struct FrisbeeApproach
	{
		public readonly Vector3 Direction;

		public readonly string Name;

		public FrisbeeApproach(Vector3 direction, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			Direction = direction;
			Name = name;
		}
	}

	private enum FrisbeeShapeKind
	{
		Box,
		Sphere,
		Capsule,
		ConvexMesh
	}

	private sealed class FrisbeeShape
	{
		public readonly FrisbeeShapeKind Kind;

		public readonly Vector3 LocalCenter;

		public readonly Vector3 ProbeLocalOrigin;

		public readonly Quaternion LocalRotation;

		public readonly Vector3 Dimensions;

		public readonly float Radius;

		public readonly float Height;

		public readonly Vector3 CapsuleAxis;

		public readonly Mesh Mesh;

		public readonly Collider ProbeCollider;

		public readonly Collider SourceCollider;

		public FrisbeeShape(FrisbeeShapeKind kind, Vector3 localCenter, Vector3 probeLocalOrigin, Quaternion localRotation, Vector3 dimensions, float radius, float height, int capsuleDirection, Mesh mesh, Collider probeCollider, Collider sourceCollider)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_001e: 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_0026: 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)
			//IL_0058: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			Kind = kind;
			LocalCenter = localCenter;
			ProbeLocalOrigin = probeLocalOrigin;
			LocalRotation = localRotation;
			Dimensions = dimensions;
			Radius = radius;
			Height = height;
			CapsuleAxis = (Vector3)(capsuleDirection switch
			{
				2 => Vector3.forward, 
				0 => Vector3.right, 
				_ => Vector3.up, 
			});
			Mesh = mesh;
			ProbeCollider = probeCollider;
			SourceCollider = sourceCollider;
		}
	}

	private sealed class FrisbeeGeometry
	{
		public readonly List<FrisbeeShape> Shapes = new List<FrisbeeShape>();

		public GameObject SourceObject;

		public GameObject ProbeRoot;

		public Vector3 SourcePosition;

		public Quaternion SourceRotation;

		public float BoundingRadius
		{
			get
			{
				float num = 0f;
				for (int i = 0; i < Shapes.Count; i++)
				{
					FrisbeeShape frisbeeShape = Shapes[i];
					float num2 = ((frisbeeShape.Kind == FrisbeeShapeKind.Sphere) ? frisbeeShape.Radius : ((frisbeeShape.Kind == FrisbeeShapeKind.Capsule) ? Mathf.Sqrt(frisbeeShape.Radius * frisbeeShape.Radius + frisbeeShape.Height * frisbeeShape.Height * 0.25f) : (((Vector3)(ref frisbeeShape.Dimensions)).magnitude * 0.5f)));
					num = Mathf.Max(num, ((Vector3)(ref frisbeeShape.LocalCenter)).magnitude + num2);
				}
				return num;
			}
		}

		public void SetPose(Vector3 position, Quaternion rotation)
		{
			//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_0049: 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)
			if ((Object)(object)ProbeRoot != (Object)null)
			{
				ProbeRoot.transform.SetPositionAndRotation(position, rotation);
				for (int i = 0; i < Shapes.Count; i++)
				{
					((Component)Shapes[i].ProbeCollider).transform.localPosition = Shapes[i].ProbeLocalOrigin;
					((Component)Shapes[i].ProbeCollider).transform.localRotation = Shapes[i].LocalRotation;
				}
			}
		}

		public float GetForwardExtent(Vector3 direction, Quaternion rootRotation)
		{
			//IL_0006: 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)
			return Mathf.Max(0.001f, GetSignedSupportExtent(direction, rootRotation));
		}

		public float GetSignedSupportExtent(Vector3 direction, Quaternion rootRotation)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_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)
			//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_0050: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0068: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00ff: 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_0106: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_00a1: 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_00a8: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			if (Shapes.Count == 0)
			{
				return 0f;
			}
			float num = float.NegativeInfinity;
			for (int i = 0; i < Shapes.Count; i++)
			{
				FrisbeeShape frisbeeShape = Shapes[i];
				Vector3 val = rootRotation * frisbeeShape.LocalCenter;
				Vector3 val2 = rootRotation * frisbeeShape.LocalRotation * Vector3.right;
				Vector3 val3 = rootRotation * frisbeeShape.LocalRotation * Vector3.up;
				Vector3 val4 = rootRotation * frisbeeShape.LocalRotation * Vector3.forward;
				float num2;
				if (frisbeeShape.Kind == FrisbeeShapeKind.Sphere)
				{
					num2 = frisbeeShape.Radius;
				}
				else if (frisbeeShape.Kind == FrisbeeShapeKind.Capsule)
				{
					Vector3 val5 = rootRotation * frisbeeShape.LocalRotation * frisbeeShape.CapsuleAxis;
					float num3 = Mathf.Max(0f, frisbeeShape.Height * 0.5f - frisbeeShape.Radius);
					num2 = frisbeeShape.Radius + num3 * Mathf.Abs(Vector3.Dot(direction, val5));
				}
				else
				{
					Vector3 val6 = frisbeeShape.Dimensions * 0.5f;
					num2 = Mathf.Abs(Vector3.Dot(direction, val2)) * val6.x + Mathf.Abs(Vector3.Dot(direction, val3)) * val6.y + Mathf.Abs(Vector3.Dot(direction, val4)) * val6.z;
				}
				num = Mathf.Max(num, Vector3.Dot(val, direction) + num2);
			}
			return num;
		}

		public Bounds GetBounds(Vector3 position, Quaternion rotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0048: 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_004f: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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_014f: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: 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_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00e3: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_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_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: 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_021c: Unknown result type (might be due to invalid IL or missing references)
			Bounds result = default(Bounds);
			((Bounds)(ref result))..ctor(position, Vector3.zero);
			bool flag = false;
			Vector3 val5 = default(Vector3);
			Bounds val8 = default(Bounds);
			for (int i = 0; i < Shapes.Count; i++)
			{
				FrisbeeShape frisbeeShape = Shapes[i];
				Vector3 val = position + rotation * frisbeeShape.LocalCenter;
				Vector3 val2 = rotation * frisbeeShape.LocalRotation * Vector3.right;
				Vector3 val3 = rotation * frisbeeShape.LocalRotation * Vector3.up;
				Vector3 val4 = rotation * frisbeeShape.LocalRotation * Vector3.forward;
				if (frisbeeShape.Kind == FrisbeeShapeKind.Sphere)
				{
					val5 = Vector3.one * frisbeeShape.Radius;
				}
				else if (frisbeeShape.Kind == FrisbeeShapeKind.Capsule)
				{
					Vector3 val6 = rotation * frisbeeShape.LocalRotation * frisbeeShape.CapsuleAxis;
					float num = Mathf.Max(0f, frisbeeShape.Height * 0.5f - frisbeeShape.Radius);
					val5 = Vector3.one * frisbeeShape.Radius + new Vector3(Mathf.Abs(val6.x), Mathf.Abs(val6.y), Mathf.Abs(val6.z)) * num;
				}
				else
				{
					Vector3 val7 = frisbeeShape.Dimensions * 0.5f;
					((Vector3)(ref val5))..ctor(Mathf.Abs(val2.x) * val7.x + Mathf.Abs(val3.x) * val7.y + Mathf.Abs(val4.x) * val7.z, Mathf.Abs(val2.y) * val7.x + Mathf.Abs(val3.y) * val7.y + Mathf.Abs(val4.y) * val7.z, Mathf.Abs(val2.z) * val7.x + Mathf.Abs(val3.z) * val7.y + Mathf.Abs(val4.z) * val7.z);
				}
				((Bounds)(ref val8))..ctor(val, val5 * 2f);
				if (!flag)
				{
					result = val8;
					flag = true;
				}
				else
				{
					((Bounds)(ref result)).Encapsulate(val8);
				}
			}
			return result;
		}
	}

	private sealed class ItemEntry
	{
		public readonly Item Item;

		public readonly string PrefabName;

		public readonly string Token;

		public readonly ushort ItemId;

		public ItemEntry(Item item, string prefabName, string token)
		{
			Item = item;
			PrefabName = prefabName;
			Token = token;
			ItemId = (ushort)((!((Object)(object)item == (Object)null)) ? item.itemID : 0);
		}
	}

	private sealed class RescueTargetSnapshot
	{
		public readonly Character Actor;

		public readonly Vector3 Center;

		public readonly List<Collider> Body;

		public readonly Bounds Bounds;

		public readonly Item HeldItem;

		public RescueTargetSnapshot(Character actor, Vector3 center, List<Collider> body, Bounds bounds)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			Actor = actor;
			Center = center;
			Body = body;
			Bounds = bounds;
			HeldItem = (((Object)(object)actor == (Object)null || (Object)(object)actor.data == (Object)null) ? null : actor.data.currentItem);
		}
	}

	private sealed class RescuePlan
	{
		public readonly Vector3 FixedCenter;

		public readonly float ModelLength;

		public readonly Vector3 ExpectedSurface;

		public readonly Vector3 Position;

		public readonly Quaternion Rotation;

		public RescuePlan(Vector3 fixedCenter, float modelLength, Vector3 expectedSurface, Vector3 position, Quaternion rotation)
		{
			//IL_0007: 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_0015: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			FixedCenter = fixedCenter;
			ModelLength = modelLength;
			ExpectedSurface = expectedSurface;
			Position = position;
			Rotation = rotation;
		}
	}

	private sealed class RescueWarpOperation
	{
		public readonly Character Target;

		public readonly int TargetId;

		public readonly Vector3 FixedCenter;

		public readonly RescueWarpState State = new RescueWarpState();

		public Action<Character> CompletionHandler;

		public bool Subscribed;

		public bool Cancelled;

		public bool CleanupDone;

		public Coroutine Coroutine;

		public RescueWarpOperation(Character target, int targetId, Vector3 fixedCenter)
		{
			//IL_0020: 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)
			Target = target;
			TargetId = targetId;
			FixedCenter = fixedCenter;
		}
	}

	private sealed class RescueCandidateObservation
	{
		public readonly Character Actor;

		public readonly string Reason;

		public readonly float Distance;

		public RescueCandidateObservation(Character actor, string reason, float distance)
		{
			Actor = actor;
			Reason = reason;
			Distance = distance;
		}
	}

	private sealed class RescuePlatformGeometry
	{
		private readonly List<RescuePlatformCollider> _colliders;

		private RescuePlatformGeometry(List<RescuePlatformCollider> colliders)
		{
			_colliders = colliders;
		}

		public static bool TryCapture(GameObject prefab, out RescuePlatformGeometry geometry, out string error)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			geometry = null;
			error = "native platform has no enabled solid collider";
			if ((Object)(object)prefab == (Object)null)
			{
				return false;
			}
			Transform transform = prefab.transform;
			List<RescuePlatformCollider> list = new List<RescuePlatformCollider>();
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (IsPrefabSolid(val) && IsPrefabHierarchyEnabled(((Component)val).transform, transform))
				{
					if (!TryGetLocalGeometryBounds(val, transform, out var localBounds, out error))
					{
						return false;
					}
					list.Add(new RescuePlatformCollider(((Component)val).gameObject.layer, localBounds));
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			geometry = new RescuePlatformGeometry(list);
			error = null;
			return true;
		}

		public bool HasCollisionWithBody(List<Collider> body)
		{
			foreach (RescuePlatformCollider collider in _colliders)
			{
				if (RescueLayerCollidesWithBody(collider.Layer, body))
				{
					return true;
				}
			}
			return false;
		}

		public bool TryGetBounds(Vector3 rootPosition, Quaternion rootRotation, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0077: 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)
			bounds = default(Bounds);
			bool flag = false;
			foreach (RescuePlatformCollider collider in _colliders)
			{
				Bounds val = TransformBounds(collider.LocalBounds, rootPosition, rootRotation);
				if (!flag)
				{
					bounds = val;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val);
				}
			}
			if (flag && IsFiniteVector(((Bounds)(ref bounds)).center) && IsFiniteVector(((Bounds)(ref bounds)).size))
			{
				Vector3 size = ((Bounds)(ref bounds)).size;
				return ((Vector3)(ref size)).sqrMagnitude > 0f;
			}
			return false;
		}

		private static bool TryGetLocalGeometryBounds(Collider collider, Transform root, out Bounds localBounds, out string error)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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)
			//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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00df: 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_0142: 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_0110: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			localBounds = default(Bounds);
			error = "unsupported native platform collider geometry: " + ((object)collider).GetType().Name;
			BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null);
			if (val != null)
			{
				localBounds = TransformBoundsToRoot(((Component)val).transform, new Bounds(val.center, val.size), root);
			}
			else
			{
				SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null);
				if (val2 != null)
				{
					localBounds = TransformBoundsToRoot(((Component)val2).transform, new Bounds(val2.center, Vector3.one * (val2.radius * 2f)), root);
				}
				else
				{
					CapsuleCollider val3 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null);
					if (val3 != null)
					{
						Vector3 val4 = Vector3.one * (val3.radius * 2f);
						((Vector3)(ref val4))[val3.direction] = val3.height;
						localBounds = TransformBoundsToRoot(((Component)val3).transform, new Bounds(val3.center, val4), root);
					}
					else
					{
						MeshCollider val5 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null);
						if (val5 == null || !((Object)(object)val5.sharedMesh != (Object)null))
						{
							return false;
						}
						localBounds = TransformBoundsToRoot(((Component)val5).transform, val5.sharedMesh.bounds, root);
					}
				}
			}
			error = null;
			if (IsFiniteVector(((Bounds)(ref localBounds)).center) && IsFiniteVector(((Bounds)(ref localBounds)).size))
			{
				Vector3 size = ((Bounds)(ref localBounds)).size;
				return ((Vector3)(ref size)).sqrMagnitude > 0f;
			}
			return false;
		}

		private static Bounds TransformBoundsToRoot(Transform child, Bounds childBounds, Transform root)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_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)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0065: 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)
			Vector3 val = child.TransformPoint(GetBoundsCorner(childBounds, 0));
			Vector3 val2 = Quaternion.Inverse(root.rotation) * (val - root.position);
			Bounds result = default(Bounds);
			((Bounds)(ref result))..ctor(val2, Vector3.zero);
			for (int i = 1; i < 8; i++)
			{
				Vector3 val3 = child.TransformPoint(GetBoundsCorner(childBounds, i));
				((Bounds)(ref result)).Encapsulate(Quaternion.Inverse(root.rotation) * (val3 - root.position));
			}
			return result;
		}

		private static bool IsPrefabSolid(Collider collider)
		{
			if ((Object)(object)collider != (Object)null && collider.enabled && !collider.isTrigger)
			{
				if (!((Object)(object)collider.attachedRigidbody == (Object)null))
				{
					return collider.attachedRigidbody.detectCollisions;
				}
				return true;
			}
			return false;
		}

		private static Bounds TransformBounds(Bounds localBounds, Vector3 position, Quaternion rotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_002e: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			Bounds result = default(Bounds);
			((Bounds)(ref result))..ctor(position + rotation * GetBoundsCorner(localBounds, 0), Vector3.zero);
			for (int i = 1; i < 8; i++)
			{
				((Bounds)(ref result)).Encapsulate(position + rotation * GetBoundsCorner(localBounds, i));
			}
			return result;
		}

		private static Vector3 GetBoundsCorner(Bounds bounds, int index)
		{
			//IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_003b: 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)
			Vector3 min = ((Bounds)(ref bounds)).min;
			Vector3 max = ((Bounds)(ref bounds)).max;
			return new Vector3(((index & 1) == 0) ? min.x : max.x, ((index & 2) == 0) ? min.y : max.y, ((index & 4) == 0) ? min.z : max.z);
		}

		private static bool IsPrefabHierarchyEnabled(Transform child, Transform root)
		{
			Transform val = child;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					return false;
				}
				val = val.parent;
			}
			return true;
		}
	}

	private readonly struct RescuePlatformCollider
	{
		public readonly int Layer;

		public readonly Bounds LocalBounds;

		public RescuePlatformCollider(int layer, Bounds localBounds)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Layer = layer;
			LocalBounds = localBounds;
		}
	}

	public const string PluginGuid = "rua.PingPointUseItem";

	public const string PluginName = "Ping Point Use Item";

	public const string PluginVersion = "2.6.14";

	private const string DefaultItem = "Cure-All";

	private const string DefaultWheelItems = "Cure-All;Dynamite;AntiZooka;Frisbee;PandorasBox;曲迁菇;踏板菇;灵药菇";

	private const string CookingMode = "Cooking";

	private const string CollisionMode = "Collision";

	private const string UnlimitedUsageMode = "Unlimited";

	private const string LimitedUsageMode = "Limited";

	private const int WheelSliceCount = 8;

	private const float SurfaceOffset = 0.08f;

	private const float ConservativeSpawnOffset = 1.5f;

	private const float InitializationTimeoutSeconds = 5f;

	private const float CleanupTimeoutSeconds = 1.5f;

	private const float ThrowWindowSafetySeconds = 0.01f;

	private const int WarpCollisionWindowMarginFixedSteps = 2;

	private const int WarpPreferredFlightFixedSteps = 4;

	private const int WarpThrownDataReadinessFixedSteps = 4;

	private const float WarpLaunchSpeedMargin = 0.5f;

	private const float WarpStrictSpeedMargin = 0.01f;

	private const float ThrowAmount = 1f;

	private const float GenericCollisionLaunchSpeed = 8f;

	private const float MaximumCleanupDelaySeconds = 30f;

	private const float FrisbeeDefaultTargetSearchRadius = 5f;

	private const float FrisbeeDefaultSpeed = 60f;

	private const float FrisbeeDefaultLifetimeSeconds = 0.5f;

	private const float FrisbeeMinimumClearance = 0.15f;

	private const float FrisbeeMaximumTargetSearchRadius = 30f;

	private const float FrisbeeMaximumSpeed = 200f;

	private const float FrisbeeMaximumLifetimeSeconds = 10f;

	private const float FrisbeePathTieEpsilon = 0.001f;

	private const float FrisbeeStartSurfaceEpsilon = 0.01f;

	private const int FrisbeeDirectPoseIterations = 4;

	private const int FrisbeeOverlapCapacity = 256;

	private const int FrisbeeCastCapacity = 128;

	private const int ArrowFrisbeeCandidateLimit = 128;

	private const float ArrowFrisbeePlacementStep = 0.025f;

	private const float ArrowFrisbeeOriginEpsilon = 0.001f;

	private static Plugin _instance;

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<string> _item;

	private ConfigEntry<string> _usageMode;

	private ConfigEntry<string> _cureAllMode;

	private ConfigEntry<string> _dynamiteMode;

	private ConfigEntry<string> _antiZookaMode;

	private ConfigEntry<string> _pandorasBoxMode;

	private ConfigEntry<string> _warpFungusMode;

	private ConfigEntry<string> _stepMushroomMode;

	private ConfigEntry<string> _elixirMushroomMode;

	private ConfigEntry<float> _collisionCleanupDelaySeconds;

	private ConfigEntry<float> _frisbeeTargetSearchRadius;

	private ConfigEntry<float> _frisbeeSpeed;

	private ConfigEntry<float> _frisbeeLifetimeSeconds;

	private Harmony _harmony;

	private FieldInfo _chosenEmoteData;

	private FieldInfo _emoteWheelPage;

	private GameObject _customWheelObject;

	private EmoteWheel _customWheel;

	private CustomWheelMarker _customMarker;

	private Character _wheelCharacter;

	private CharacterData _wheelCharacterData;

	private bool _customWheelActive;

	private bool _closingWheel;

	private bool _previousUsingEmoteWheel;

	private List<ItemEntry> _wheelItems;

	private List<ItemEntry> _resolvedWheelItems;

	private bool _wheelDataRebuildPending;

	private string _resolvedWheelConfig;

	private readonly List<Sprite> _createdSprites = new List<Sprite>();

	private readonly List<EmoteWheelData> _createdData = new List<EmoteWheelData>();

	private readonly List<TextMeshProUGUI> _createdCountLabels = new List<TextMeshProUGUI>();

	private readonly QuotaLabelPresentation[] _countLabelPresentations = new QuotaLabelPresentation[8];

	private readonly Dictionary<ushort, int> _remainingUsage = new Dictionary<ushort, int>();

	private readonly HashSet<ushort> _finiteUsageItemIds = new HashSet<ushort>();

	private bool _canonicalUsageIdsResolved;

	private bool _canonicalFrisbeeIdResolved;

	private ushort _canonicalFrisbeeItemId;

	private readonly StageRewardTracker _stageRewardTracker = new StageRewardTracker();

	private readonly WheelRefreshTracker _wheelRefresh = new WheelRefreshTracker();

	private int _wheelSpectatorFrame = -1;

	private bool _wheelSpectatingSnapshot;

	private int _segmentSpawnSyncDepth;

	private bool _stageRebaselinePending;

	private MapHandler _observedMapHandler;

	private readonly HashSet<int> _reclaimAttemptedInstances = new HashSet<int>();

	private readonly HashSet<int> _reclaimValidationLogged = new HashSet<int>();

	private readonly Dictionary<int, GameObject> _pendingFrisbeeObjects = new Dictionary<int, GameObject>();

	private GameObject _countOverlayObject;

	private RectTransform _countOverlayRect;

	private Canvas _countOverlayCanvas;

	private bool _countLayoutPending;

	private bool _countDiagnosticLogged;

	private int _countLayoutFramesRemaining;

	private readonly Vector3[] _countWorldCorners = (Vector3[])(object)new Vector3[4];

	private MethodInfo _pingablePropsResolveMethod;

	private bool _pingablePropsResolveSearched;

	private string _lastValidationError;

	private int _lastHandledPingFrame = -1;

	private string _observedUsageMode;

	private readonly Collider[] _frisbeeOverlapBuffer = (Collider[])(object)new Collider[256];

	private readonly RaycastHit[] _frisbeeCastBuffer = (RaycastHit[])(object)new RaycastHit[128];

	private Type _ghostFreeSyncType;

	private PropertyInfo _ghostFreeFlyProperty;

	private float _nextGhostFreeSyncResolveTime;

	private FieldInfo _sliceEmoteData;

	private MethodInfo _pingInCooldown;

	private bool _pingHitHookReady;

	private bool _canPingHookReady;

	private bool _pingSampleHookReady;

	private readonly HashSet<string> _pingSupplementWarnings = new HashSet<string>();

	private static readonly FieldInfo ArrowShooterPosition = AccessTools.Field(typeof(ArrowShooter), "pos");

	private static readonly FieldInfo ArrowShooterForward = AccessTools.Field(typeof(ArrowShooter), "forward");

	internal const float MusicTrailInitializationTimeoutSeconds = 5f;

	internal const float MusicTrailDefaultSpacingMeters = 8f;

	internal const float MusicTrailDefaultInitialEmissionSeconds = 0.01f;

	internal const float MusicTrailMinimumSpacingMeters = 0.1f;

	internal const float MusicTrailMaximumSpacingMeters = 100f;

	internal const float MusicTrailMinimumInitialEmissionSeconds = 0.01f;

	internal const float MusicTrailMaximumInitialEmissionSeconds = 0.9f;

	internal const int MusicTrailMaximumInstances = 32;

	internal const float MusicTrailParkY = -1000f;

	internal const float MusicTrailPositionTolerance = 0.0005f;

	internal const float MusicTrailDefaultEffectPlaybackSeconds = 3f;

	internal const float MusicTrailDefaultDestroyDelaySeconds = 0f;

	internal const float MusicTrailMinimumStageSeconds = 0f;

	internal const float MusicTrailMaximumStageSeconds = 8f;

	internal const float MusicTrailEndTootFailureTimeoutSeconds = 3f;

	private ConfigEntry<bool> _musicTrailEnabled;

	private ConfigEntry<float> _musicTrailSpacing;

	private ConfigEntry<float> _musicTrailInitialEmissionSeconds;

	private ConfigEntry<float> _musicTrailEffectPlaybackSeconds;

	private ConfigEntry<float> _musicTrailDestroyDelaySeconds;

	private bool _musicTrailHookReady;

	private Coroutine _musicTrailSpawnCoroutine;

	private bool _musicTrailBatchActive;

	private bool _musicTrailBatchCancelRequested;

	private int _musicTrailBatchSequence;

	private int _musicTrailBatchExpected;

	private int _musicTrailBatchSpawned;

	private readonly Dictionary<int, MusicTrailController> _musicTrailControllers = new Dictionary<int, MusicTrailController>();

	private readonly Dictionary<int, GameObject> _pendingMusicTrailObjects = new Dictionary<int, GameObject>();

	private ConfigEntry<bool> _rescueEnabled;

	private ConfigEntry<float> _rescueRadius;

	private ConfigEntry<float> _rescueMinimumClearance;

	private readonly RescueDiagnosticThrottle _rescueErrorThrottle = new RescueDiagnosticThrottle();

	private readonly RescueDiagnosticThrottle _rescueSelectionThrottle = new RescueDiagnosticThrottle();

	private readonly HashSet<int> _rescuePendingTargets = new HashSet<int>();

	private readonly HashSet<RescueWarpOperation> _rescueOperations = new HashSet<RescueWarpOperation>();

	private readonly Dictionary<int, RescueWarpOperation> _rescueOperationsByTarget = new Dictionary<int, RescueWarpOperation>();

	private Collider[] _rescueOverlapBuffer = (Collider[])(object)new Collider[32];

	private RaycastHit[] _rescueClearanceHits = (RaycastHit[])(object)new RaycastHit[32];

	private static readonly FieldInfo RescueBodyColliders = AccessTools.Field(typeof(CharacterRagdoll), "colliderList");

	private static readonly FieldInfo RescueLastWarpTarget = AccessTools.Field(typeof(Character), "_lastWarpTarget");

	private ItemDatabase _rescueCachedDatabase;

	private object _rescueCachedDatabaseObjects;

	private GameObject _rescueCachedPrefab;

	private string _rescueCachedResource;

	private RescuePlatformGeometry _rescueCachedGeometry;

	private CloudFungus _rescueCachedFungus;

	private GameObject _rescueCachedInstantiateOnBreak;

	private int _rescueCachedSceneHandle = -1;

	internal static string ArrowSyncMode
	{
		get
		{
			if (!PhotonNetwork.OfflineMode)
			{
				return "online nativeforcedsync";
			}
			return "offline localphysics";
		}
	}

	internal ManualLogSource MusicTrailLogger => ((BaseUnityPlugin)this).Logger;

	private void Awake()
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Expected O, but got Unknown
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Expected O, but got Unknown
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Expected O, but got Unknown
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Expected O, but got Unknown
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Expected O, but got Unknown
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Expected O, but got Unknown
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Expected O, but got Unknown
		_instance = this;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "启用所有角色状态的原生 Ping 生成与 Z 轮盘;保留原绑定、冷却和菜单限制,不启用被禁用的输入 action。 / Enable native Ping spawning and the Z wheel in all character states; preserve bindings, cooldown and menu guards without enabling disabled input actions.");
		_item = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Item", "Cure-All", new ConfigDescription("下一次成功 Ping 使用的物品;由 Z 键轮盘选择并持久化。 / Item used by the next successful Ping; selected and persisted by the Z-key wheel.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[8] { "Cure-All", "Dynamite", "AntiZooka", "Frisbee", "PandorasBox", "曲迁菇", "踏板菇", "灵药菇" }), Array.Empty<object>()));
		_usageMode = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Usage Mode", "Unlimited", new ConfigDescription("物品配额模式;Limited 新阶段为七种有限物品各加一份,观战临时 Unlimited 不重置配额。 / Usage quotas; Limited adds one use per finite item on a new stage; spectator Unlimited is temporary and does not reset quotas.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Unlimited", "Limited" }), Array.Empty<object>()));
		_observedUsageMode = _usageMode.Value;
		_usageMode.SettingChanged += UsageModeSettingChanged;
		_cureAllMode = BindTriggerMode("Cure-All", "Cooking");
		_dynamiteMode = BindTriggerMode("Dynamite", "Cooking");
		_antiZookaMode = BindTriggerMode("AntiZooka", "Cooking");
		_pandorasBoxMode = BindTriggerMode("PandorasBox", "Cooking");
		_warpFungusMode = BindTriggerMode("WarpFungus", "Collision");
		_stepMushroomMode = BindTriggerMode("踏板菇", "Collision");
		_elixirMushroomMode = BindTriggerMode("灵药菇", "Collision");
		_collisionCleanupDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Collision", "Cleanup Delay Seconds", 0.5f, new ConfigDescription("碰撞物品在施加速度后保留的原始网络物品清理延迟(秒),仅清理原始物品,不清理效果子物体。 / Seconds to keep the original network collision item after velocity is assigned; effect children are untouched.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
		_frisbeeTargetSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "Target Search Radius", 5f, new ConfigDescription("以本次成功 Ping 的 point 为中心搜索目标,单位为米。 / Search around this successful Ping point, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f), Array.Empty<object>()));
		_frisbeeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "Speed", 60f, new ConfigDescription("Frisbee 释放速度(米/秒)。 / Frisbee release speed in meters per second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
		_frisbeeLifetimeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Throw", "Lifetime Seconds", 0.5f, new ConfigDescription("Frisbee 从实际释放开始的最长存活时间(秒)。 / Maximum Frisbee lifetime in seconds from the actual launch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), Array.Empty<object>()));
		BindMusicTrailSettings();
		BindRescueSettings();
		_chosenEmoteData = typeof(EmoteWheel).GetField("chosenEmoteData", BindingFlags.Instance | BindingFlags.NonPublic);
		_emoteWheelPage = typeof(EmoteWheel).GetField("page", BindingFlags.Instance | BindingFlags.NonPublic);
		_sliceEmoteData = typeof(EmoteWheelSlice).GetField("emoteData", BindingFlags.Instance | BindingFlags.NonPublic);
		_harmony = new Harmony("rua.PingPointUseItem");
		PatchVanillaWheel();
		PatchMusicTrail();
		PatchVanillaPing();
		SceneManager.activeSceneChanged += OnActiveSceneChanged;
		LocalizedText.OnLangugageChanged = (Action)Delegate.Combine(LocalizedText.OnLangugageChanged, new Action(OnLanguageChanged));
	}

	private void UsageModeSettingChanged(object sender, EventArgs e)
	{
		SyncUsageMode();
	}

	private void PatchVanillaWheel()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Expected O, but got Unknown
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Expected O, but got Unknown
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Expected O, but got Unknown
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Expected O, but got Unknown
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Expected O, but got Unknown
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Expected O, but got Unknown
		//IL_0193: Expected O, but got Unknown
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Expected O, but got Unknown
		//IL_01f0: Expected O, but got Unknown
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Expected O, but got Unknown
		PatchOptional(AccessTools.Method(typeof(GUIManager), "UpdateEmoteWheel", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "UpdateEmoteWheelPrefix", (Type[])null), null, "GUIManager.UpdateEmoteWheel");
		PatchOptional(AccessTools.PropertyGetter(typeof(GUIManager), "wheelActive"), null, new HarmonyMethod(typeof(Plugin), "WheelActivePostfix", (Type[])null), "GUIManager.wheelActive");
		PatchOptional(AccessTools.Method(typeof(EmoteWheel), "Choose", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "ChoosePrefix", (Type[])null), null, "EmoteWheel.Choose");
		PatchOptional(AccessTools.Method(typeof(EmoteWheel), "Tab", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "TabPrefix", (Type[])null), null, "EmoteWheel.Tab");
		PatchOptional(AccessTools.Method(typeof(EmoteWheel), "Hover", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "HoverPrefix", (Type[])null), null, "EmoteWheel.Hover");
		PatchOptional(AccessTools.Method(typeof(EmoteWheelSlice), "Hover", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "SliceHoverPrefix", (Type[])null), null, "EmoteWheelSlice.Hover");
		PatchOptional(AccessTools.Method(typeof(Character), "Start", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "CharacterStartPrefix", (Type[])null), new HarmonyMethod(typeof(Plugin), "CharacterStartPostfix", (Type[])null), "Character.Start");
		PatchOptional(AccessTools.Method(typeof(Character), "ReviveCharacter", new Type[1] { typeof(bool) }, (Type[])null), new HarmonyMethod(typeof(Plugin), "ReviveCharacterPrefix", (Type[])null), new HarmonyMethod(typeof(Plugin), "ReviveCharacterPostfix", (Type[])null), "Character.ReviveCharacter");
		PatchOptional(AccessTools.Method(typeof(RunManager), "StartRun", (Type[])null, (Type[])null), null, new HarmonyMethod(typeof(Plugin), "StartRunPostfix", (Type[])null), "RunManager.StartRun");
		PatchSetSegmentOnSpawn();
	}

	private void PatchOptional(MethodBase target, HarmonyMethod prefix, HarmonyMethod postfix, string label)
	{
		if (target == null)
		{
			return;
		}
		try
		{
			_harmony.Patch(target, prefix, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch " + label + ": " + ex));
		}
	}

	private void PatchSetSegmentOnSpawn()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		//IL_005b: Expected O, but got Unknown
		MethodInfo methodInfo = AccessTools.Method(typeof(MapHandler), "SetSegmentOnSpawn", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			return;
		}
		try
		{
			_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "SetSegmentOnSpawnPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "SetSegmentOnSpawnFinalizer", (Type[])null), (HarmonyMethod)null);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch MapHandler.SetSegmentOnSpawn with an exception-safe finalizer: " + ex));
		}
	}

	private void PatchVanillaPing()
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Expected O, but got Unknown
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Expected O, but got Unknown
		try
		{
			MethodInfo method = typeof(PointPinger).GetMethod("TryGetPingHit", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[2]
			{
				typeof(RaycastHit).MakeByRefType(),
				typeof(Vector3)
			}, null);
			if (method == null)
			{
				throw new MissingMethodException("PointPinger.TryGetPingHit(out RaycastHit, Vector3)");
			}
			_harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "VanillaPingHitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_pingHitHookReady = true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch PointPinger.TryGetPingHit; item spawning is disabled because the vanilla ping hit source is unavailable: " + ex));
		}
		try
		{
			_pingInCooldown = AccessTools.Method(typeof(PointPinger), "get_inCooldown", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo = AccessTools.Method(typeof(PointPinger), "get_canPing", Type.EmptyTypes, (Type[])null);
			if (_pingInCooldown == null || _pingInCooldown.ReturnType != typeof(bool) || methodInfo == null || methodInfo.ReturnType != typeof(bool))
			{
				throw new MissingMethodException("PointPinger.get_canPing/get_inCooldown()");
			}
			_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "CanPingPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_canPingHookReady = true;
		}
		catch (Exception ex2)
		{
			LogPingSupplementWarning("can-ping-hook", "Non-conscious Ping adaptation unavailable: " + ex2.Message);
		}
		try
		{
			MethodInfo methodInfo2 = AccessTools.Method(typeof(CharacterInput), "Sample", new Type[1] { typeof(bool) }, (Type[])null);
			if (methodInfo2 == null)
			{
				throw new MissingMethodException("CharacterInput.Sample(bool)");
			}
			_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "PingSamplePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_pingSampleHookReady = true;
		}
		catch (Exception ex3)
		{
			LogPingSupplementWarning("sample-hook", "Supplemental Ping input unavailable: " + ex3.Message);
		}
	}

	private void LogPingSupplementWarning(string reason, string detail)
	{
		if (_pingSupplementWarnings.Add(reason))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)(detail + "; no action enabling, synthetic input, or replacement Ping is attempted."));
		}
	}

	private bool TryReadPingCooldown(PointPinger pinger, out bool inCooldown)
	{
		inCooldown = true;
		if (_pingInCooldown == null || !_pingHitHookReady)
		{
			LogPingSupplementWarning("cooldown-hook", "Native Ping hit/cooldown hooks are unavailable");
			return false;
		}
		try
		{
			inCooldown = (bool)_pingInCooldown.Invoke(pinger, null);
			return true;
		}
		catch (Exception ex)
		{
			LogPingSupplementWarning("cooldown-read", "Native Ping cooldown could not be read: " + ex.Message);
			return false;
		}
	}

	private static void CanPingPostfix(PointPinger __instance, ref bool __result)
	{
		Plugin instance = _instance;
		Character localCharacter = Character.localCharacter;
		if (!((Object)(object)instance == (Object)null) && instance._enabled.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)localCharacter == (Object)null) && !((Object)(object)localCharacter.data == (Object)null) && !localCharacter.data.fullyConscious && instance.IsLocalVanillaPingOwner(localCharacter, __instance))
		{
			bool flag = instance.ArePingGuardsValid(localCharacter, __instance);
			bool cooldownKnown = false;
			bool inCooldown = true;
			if (flag)
			{
				cooldownKnown = instance.TryReadPingCooldown(__instance, out inCooldown);
			}
			__result = PingAccessPolicy.AdaptCanPing(__result, enabled: true, localOwner: true, fullyConscious: false, flag, cooldownKnown, inCooldown);
		}
	}

	private static void PingSamplePostfix(CharacterInput __instance)
	{
		Plugin instance = _instance;
		Character localCharacter = Character.localCharacter;
		if ((Object)(object)instance == (Object)null || !instance._enabled.Value || !instance._pingSampleHookReady || (Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || localCharacter.data.fullyConscious || (Object)(object)__instance == (Object)null || (Object)(object)localCharacter.input != (Object)(object)__instance || !((Behaviour)__instance).isActiveAndEnabled)
		{
			return;
		}
		if (!instance._canPingHookReady)
		{
			instance.LogPingSupplementWarning("can-ping-hook", "Non-conscious native Ping permission hook is unavailable");
			return;
		}
		PointPinger componentInChildren = ((Component)localCharacter).GetComponentInChildren<PointPinger>(true);
		if (!instance.ArePingGuardsValid(localCharacter, componentInChildren))
		{
			return;
		}
		bool inCooldown;
		bool flag = instance.TryReadPingCooldown(componentInChildren, out inCooldown);
		if (!flag || inCooldown)
		{
			return;
		}
		InputAction action_ping = CharacterInput.action_ping;
		if (action_ping == null || !action_ping.enabled)
		{
			instance.LogPingSupplementWarning((action_ping == null) ? "ping-action-null" : "ping-action-disabled", (action_ping == null) ? "Native ping action is null" : "Native ping action is disabled");
		}
		else if (PingAccessPolicy.CanSupplement(localCharacter.data.fullyConscious, guardsValid: true, flag, inCooldown, actionExists: true, action_ping.enabled))
		{
			try
			{
				__instance.pingWasPressed |= action_ping.WasPressedThisFrame();
			}
			catch (Exception ex)
			{
				instance.LogPingSupplementWarning("ping-action-read", "Native ping action could not be sampled: " + ex.Message);
			}
		}
	}

	private void Update()
	{
		SyncUsageMode();
		ObserveStageProgression();
		if (!_enabled.Value || !Application.isFocused)
		{
			if (_customWheelActive)
			{
				AbortCustomWheel();
			}
			return;
		}
		ProcessReclaim();
		if (_customWheelActive)
		{
			ObserveCustomWheelState();
			if (_countLayoutFramesRemaining > 0)
			{
				LayoutCountLabels();
				_countLayoutFramesRemaining--;
			}
			UpdateCustomWheel();
		}
		else if (Input.GetKeyDown((KeyCode)122))
		{
			TryOpenCustomWheel();
		}
	}

	private static void VanillaPingHitPostfix(ref RaycastHit __0, bool __result)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		if (__result && (Object)(object)_instance != (Object)null)
		{
			_instance.HandleVanillaPingHit(__0);
		}
	}

	private void HandleVanillaPingHit(RaycastHit hit)
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_0191: 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_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
		{
			return;
		}
		Character localCharacter = Character.localCharacter;
		PointPinger pinger = (((Object)(object)localCharacter == (Object)null) ? null : ((Component)localCharacter).GetComponentInChildren<PointPinger>(true));
		if (!ArePingGuardsValid(localCharacter, pinger) || !TryReadPingCooldown(pinger, out var inCooldown) || inCooldown || _lastHandledPingFrame == Time.frameCount)
		{
			return;
		}
		_lastHandledPingFrame = Time.frameCount;
		try
		{
			TryStartMusicTrail(localCharacter, hit);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Music Trail failed safely without changing the native Ping item/rescue path: " + ex));
		}
		if (TryHandleFootPlatformRescue(localCharacter, hit) || !TryResolveConfiguredItem(out var item, out var prefabName))
		{
			return;
		}
		if (!CanUseItem(item.itemID))
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Ping spawn rejected by Limited quota: item='" + prefabName + "', itemID=" + item.itemID + "."));
			return;
		}
		string effectiveItemToken = GetEffectiveItemToken();
		if (IsFrisbee(item, prefabName, effectiveItemToken))
		{
			SpawnFrisbee(localCharacter, item, prefabName, hit);
			return;
		}
		string triggerMode = GetTriggerMode(item, prefabName, effectiveItemToken);
		if (string.IsNullOrEmpty(triggerMode))
		{
			return;
		}
		ItemCooking cooking;
		if (string.Equals(triggerMode, "Collision", StringComparison.OrdinalIgnoreCase))
		{
			if (TryValidateCollisionPrefab(item, prefabName, effectiveItemToken, out var kind))
			{
				if (kind == CollisionKind.WarpOnThrow && !IsTerrainCollider(((RaycastHit)(ref hit)).collider))
				{
					LogValidationError("Collision rejected for WarpFungus: the vanilla ping collider is not on HelperFunctions.terrainMapMask.");
				}
				else
				{
					SpawnCollisionItem(localCharacter, item, prefabName, hit, kind);
				}
			}
		}
		else if (TryValidateCookingPrefab(item, prefabName, out cooking))
		{
			SpawnCookingItem(item, prefabName, ((RaycastHit)(ref hit)).point + ((RaycastHit)(ref hit)).normal * 0.08f, cooking);
		}
	}

	private bool IsLocalVanillaPingOwner(Character local, PointPinger expectedPinger = null)
	{
		if ((Object)(object)local == (Object)null || !((Behaviour)local).isActiveAndEnabled || (Object)(object)local != (Object)(object)Character.localCharacter || (Object)(object)local.data == (Object)null || (Object)(object)((MonoBehaviourPun)local).photonView == (Object)null || !((MonoBehaviourPun)local).photonView.IsMine)
		{
			return false;
		}
		PointPinger val = (((Object)(object)expectedPinger != (Object)null) ? expectedPinger : ((Component)local).GetComponentInChildren<PointPinger>(true));
		if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled || (Object)(object)val.character != (Object)(object)local)
		{
			return false;
		}
		PhotonView component = ((Component)val).GetComponent<PhotonView>();
		if ((Object)(object)component != (Object)null)
		{
			return component.IsMine;
		}
		return false;
	}

	private bool ArePingGuardsValid(Character local, PointPinger pinger)
	{
		GUIManager instance = GUIManager.instance;
		PhotonView val = (((Object)(object)pinger == (Object)null) ? null : ((Component)pinger).GetComponent<PhotonView>());
		return PingAccessPolicy.CanInteract(_enabled != null && _enabled.Value, Application.isFocused, PhotonNetwork.InRoom, (Object)(object)local != (Object)null && ((Behaviour)local).isActiveAndEnabled && (Object)(object)local == (Object)(object)Character.localCharacter && (Object)(object)local.data != (Object)null, (Object)(object)pinger != (Object)null && ((Behaviour)pinger).isActiveAndEnabled && (Object)(object)pinger.character == (Object)(object)local, (Object)(object)local != (Object)null && (Object)(object)((MonoBehaviourPun)local).photonView != (Object)null && ((MonoBehaviourPun)local).photonView.IsMine, (Object)(object)val != (Object)null && val.IsMine, (Object)(object)instance == (Object)null || instance.windowBlockingInput, _customWheelActive || !NativeWheelReferencesReady(instance) || instance.wheelActive);
	}

	private static bool NativeWheelReferencesReady(GUIManager gui)
	{
		if ((Object)(object)gui != (Object)null && (Object)(object)gui.emoteWheel != (Object)null && (Object)(object)gui.backpackWheel != (Object)null)
		{
			return (Object)(object)((Component)gui.backpackWheel).gameObject != (Object)null;
		}
		return false;
	}

	private bool IsSpectating()
	{
		try
		{
			if (MainCameraMovement.IsSpectating)
			{
				return true;
			}
		}
		catch
		{
		}
		return IsOptionalGhostFreeFlyActive();
	}

	private bool IsOptionalGhostFreeFlyActive()
	{
		if (_ghostFreeSyncType == null && Time.unscaledTime >= _nextGhostFreeSyncResolveTime)
		{
			_nextGhostFreeSyncResolveTime = Time.unscaledTime + 5f;
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					Type type = assemblies[i].GetType("SymbioticGhost.GhostFreeSync", throwOnError: false);
					if (!(type == null))
					{
						PropertyInfo property = type.GetProperty("LocalFreeFlyActive", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						if (property != null && property.PropertyType == typeof(bool))
						{
							_ghostFreeSyncType = type;
							_ghostFreeFlyProperty = property;
							break;
						}
					}
				}
			}
			catch
			{
				_ghostFreeFlyProperty = null;
			}
		}
		if (_ghostFreeFlyProperty == null)
		{
			return false;
		}
		try
		{
			object obj2 = null;
			if (!_ghostFreeFlyProperty.GetMethod.IsStatic)
			{
				Object[] array = Resources.FindObjectsOfTypeAll(_ghostFreeSyncType);
				if (array == null || array.Length == 0)
				{
					return false;
				}
				obj2 = array[0];
			}
			return Convert.ToBoolean(_ghostFreeFlyProperty.GetValue(obj2, null));
		}
		catch
		{
			return false;
		}
	}

	private bool IsEffectiveLimited()
	{
		if (_usageMode != null && string.Equals(_usageMode.Value, "Limited", StringComparison.OrdinalIgnoreCase))
		{
			return !IsSpectating();
		}
		return false;
	}

	private bool IsConfiguredLimited()
	{
		if (_usageMode != null)
		{
			return string.Equals(_usageMode.Value, "Limited", StringComparison.OrdinalIgnoreCase);
		}
		return false;
	}

	private void SyncUsageMode()
	{
		string text = ((_usageMode == null) ? "Unlimited" : _usageMode.Value);
		if (string.Equals(text, _observedUsageMode, StringComparison.OrdinalIgnoreCase))
		{
			return;
		}
		bool num = string.Equals(text, "Limited", StringComparison.OrdinalIgnoreCase) && !string.Equals(_observedUsageMode, "Limited", StringComparison.OrdinalIgnoreCase);
		_observedUsageMode = text;
		if (num)
		{
			ResetAllUsageCounts();
			return;
		}
		if (!string.Equals(text, "Limited", StringComparison.OrdinalIgnoreCase))
		{
			_stageRewardTracker.ClearPendingAwards();
		}
		InvalidateCustomWheelState();
	}

	private unsafe void ObserveStageProgression()
	{
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: 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_0104: Expected I4, but got Unknown
		if (_segmentSpawnSyncDepth > 0)
		{
			return;
		}
		if (_stageRebaselinePending)
		{
			_stageRewardTracker.ResetObservation();
			_stageRewardTracker.ClearPendingAwards();
			_stageRebaselinePending = false;
		}
		if (!MapHandler.ExistsAndInitialized)
		{
			_stageRewardTracker.Observe(-1, mapReady: false, suppressed: false, rewardsEnabled: false, finiteItemsReady: false, null);
			return;
		}
		MapHandler val = _observedMapHandler;
		if ((Object)(object)val == (Object)null)
		{
			val = Singleton<MapHandler>.Instance;
		}
		if ((Object)(object)val == (Object)null)
		{
			_stageRewardTracker.Observe(-1, mapReady: false, suppressed: false, rewardsEnabled: false, finiteItemsReady: false, null);
			return;
		}
		_observedMapHandler = val;
		Segment currentSegment;
		try
		{
			currentSegment = val.GetCurrentSegment();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Stage observer could not read MapHandler.GetCurrentSegment(): " + ex.Message));
			_stageRewardTracker.Observe(-1, mapReady: false, suppressed: false, rewardsEnabled: false, finiteItemsReady: false, null);
			return;
		}
		List<ItemEntry> entries;
		bool flag = TryResolveCanonicalUsageItems(out entries);
		bool flag2 = _enabled != null && _enabled.Value && IsConfiguredLimited();
		switch (_stageRewardTracker.Observe((int)currentSegment, mapReady: true, suppressed: false, flag2, flag, AwardStage))
		{
		case StageObservation.Baseline:
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Stage observer baseline: segment=" + ((object)(*(Segment*)(&currentSegment))/*cast due to .constrained prefix*/).ToString() + "."));
			break;
		case StageObservation.Suppressed:
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Stage observer rebaseline after spawn synchronization.");
			break;
		case StageObservation.NewlyEntered:
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Stage observer entered new segment: segment=" + ((object)(*(Segment*)(&currentSegment))/*cast due to .constrained prefix*/).ToString() + "; reward=" + ((flag2 && flag) ? "awarded" : "not awarded") + "."));
			break;
		}
	}

	private void AwardStage(int stage)
	{
		if (!TryResolveCanonicalUsageItems(out var _))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Stage reward for segment " + stage + " is pending because canonical finite items are not ready."));
			return;
		}
		foreach (ushort finiteUsageItemId in _finiteUsageItemIds)
		{
			int value;
			int remaining = ((!_remainingUsage.TryGetValue(finiteUsageItemId, out value)) ? 1 : value);
			_remainingUsage[finiteUsageItemId] = UsagePolicy.AddFiniteReward(remaining);
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Stage reward awarded for segment " + stage + ": +1 to seven finite items; Frisbee unchanged."));
		InvalidateCustomWheelState();
	}

	private void EnsureUsageCounts()
	{
		if (!TryResolveCanonicalUsageItems(out var _))
		{
			return;
		}
		foreach (ushort finiteUsageItemId in _finiteUsageItemIds)
		{
			if (!_remainingUsage.ContainsKey(finiteUsageItemId))
			{
				_remainingUsage[finiteUsageItemId] = 1;
				_wheelRefresh.Invalidate();
			}
		}
	}

	private bool TryResolveCanonicalUsageItems(out List<ItemEntry> entries)
	{
		entries = null;
		if (_canonicalUsageIdsResolved && _resolvedWheelItems != null)
		{
			entries = _resolvedWheelItems;
			if (entries != null && _finiteUsageItemIds.Count == 7)
			{
				return _canonicalFrisbeeIdResolved;
			}
			return false;
		}
		if (_canonicalUsageIdsResolved && _resolvedWheelItems == null)
		{
			_canonicalUsageIdsResolved = false;
			_canonicalFrisbeeIdResolved = false;
			_finiteUsageItemIds.Clear();
		}
		if (!ResolveWheelItems(out var entries2))
		{
			return false;
		}
		if (entries2.Count != 8)
		{
			_resolvedWheelConfig = null;
			return false;
		}
		HashSet<ushort> hashSet = new HashSet<ushort>();
		bool flag = false;
		ushort canonicalFrisbeeItemId = 0;
		for (int i = 0; i < entries2.Count; i++)
		{
			ItemEntry itemEntry = entries2[i];
			if (IsFrisbee(itemEntry.Item, itemEntry.PrefabName, itemEntry.Token))
			{
				if (flag)
				{
					return false;
				}
				flag = true;
				canonicalFrisbeeItemId = itemEntry.ItemId;
			}
			else
			{
				hashSet.Add(itemEntry.ItemId);
			}
		}
		if (flag)
		{
			_canonicalFrisbeeItemId = canonicalFrisbeeItemId;
			_canonicalFrisbeeIdResolved = true;
		}
		if (!flag || hashSet.Count != 7)
		{
			return false;
		}
		_finiteUsageItemIds.Clear();
		foreach (ushort item in hashSet)
		{
			_finiteUsageItemIds.Add(item);
		}
		_canonicalUsageIdsResolved = true;
		_wheelRefresh.Invalidate();
		entries = entries2;
		return true;
	}

	private bool IsCanonicalFrisbee(ushort itemId)
	{
		if (_canonicalFrisbeeIdResolved)
		{
			return itemId == _canonicalFrisbeeItemId;
		}
		return false;
	}

	private void ResetAllUsageCounts()
	{
		EnsureUsageCounts();
		List<ushort> list = new List<ushort>(_remainingUsage.Keys);
		for (int i = 0; i < list.Count; i++)
		{
			_remainingUsage[list[i]] = 1;
		}
		_reclaimAttemptedInstances.Clear();
		_reclaimValidationLogged.Clear();
		InvalidateCustomWheelState();
	}

	private bool CanUseItem(ushort itemId)
	{
		if (!IsEffectiveLimited())
		{
			return true;
		}
		List<ItemEntry> entries;
		bool flag = TryResolveCanonicalUsageItems(out entries);
		if (IsCanonicalFrisbee(itemId))
		{
			return true;
		}
		if (!flag)
		{
			return false;
		}
		EnsureUsageCounts();
		int value;
		return UsagePolicy.CanUse(limited: true, isCanonicalFrisbee: false, _remainingUsage.TryGetValue(itemId, out value) ? value : 0);
	}

	private void ChargeSuccessfulSpawn(ushort itemId, string itemName)
	{
		if (!IsEffectiveLimited())
		{
			return;
		}
		List<ItemEntry> entries;
		bool flag = TryResolveCanonicalUsageItems(out entries);
		if (IsCanonicalFrisbee(itemId))
		{
			return;
		}
		if (!flag)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Spawn charge could not resolve canonical finite IDs for '" + itemName + "'."));
			return;
		}
		EnsureUsageCounts();
		if (!_remainingUsage.TryGetValue(itemId, out var value))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Limited usage could not resolve the canonical item ID for '" + itemName + "'."));
			return;
		}
		if (value <= 0)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Limited usage became exhausted after PhotonNetwork.Instantiate succeeded for '" + itemName + "'."));
			return;
		}
		_remainingUsage[itemId] = Mathf.Max(0, value - 1);
		InvalidateCustomWheelState();
	}

	private void ProcessReclaim()
	{
		//IL_00ef: 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_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		if (!_enabled.Value || !PhotonNetwork.InRoom || !IsEffectiveLimited())
		{
			return;
		}
		Character localCharacter = Character.localCharacter;
		if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || localCharacter.refs == null || (Object)(object)Player.localPlayer == (Object)null)
		{
			return;
		}
		Item currentItem = localCharacter.data.currentItem;
		if ((Object)(object)currentItem == (Object)null || !TryGetCanonicalItemId(currentItem.itemID))
		{
			return;
		}
		ushort itemID = currentItem.itemID;
		int instanceID = ((Object)currentItem).GetInstanceID();
		if (_reclaimAttemptedInstances.Contains(instanceID))
		{
			return;
		}
		CharacterItems items = localCharacter.refs.items;
		if ((Object)(object)items == (Object)null || (Object)(object)((MonoBehaviourPun)items).photonView == (Object)null || !((MonoBehaviourPun)items).photonView.IsMine || (Object)(object)((MonoBehaviourPun)currentItem).photonView == (Object)null || !((MonoBehaviourPun)currentItem).photonView.IsMine)
		{
			LogReclaimValidation(instanceID, "local ownership or CharacterItems PhotonView is unavailable");
			return;
		}
		Optionable<byte> currentSelectedSlot = items.currentSelectedSlot;
		if (!currentSelectedSlot.IsSome)
		{
			LogReclaimValidation(instanceID, "currentSelectedSlot is empty");
			return;
		}
		ItemSlot itemSlot = Player.localPlayer.GetItemSlot(currentSelectedSlot.Value);
		if (itemSlot == null || (Object)(object)itemSlot.prefab == (Object)null || itemSlot.prefab.itemID != currentItem.itemID)
		{
			LogReclaimValidation(instanceID, "selected inventory slot does not identify the held canonical item");
			return;
		}
		if (itemSlot.data == null || currentItem.data == null || itemSlot.data.guid == Guid.Empty || currentItem.data.guid == Guid.Empty)
		{
			LogReclaimValidation(instanceID, "ItemInstanceData GUID is unavailable or empty");
			return;
		}
		if (itemSlot.data.guid != currentItem.data.guid)
		{
			LogReclaimValidation(instanceID, "selected inventory slot ItemInstanceData GUID does not match the held item");
			return;
		}
		if (!_remainingUsage.TryGetValue(itemID, out var value))
		{
			LogReclaimValidation(instanceID, "canonical usage count is unavailable");
			return;
		}
		if (value == int.MaxValue)
		{
			LogReclaimValidation(instanceID, "usage count is already at Int32.MaxValue");
			return;
		}
		if (!TryGetCanonicalWheelId("Cure-All", out var id) || !TryGetCanonicalWheelId("PandorasBox", out var id2))
		{
			LogReclaimValidation(instanceID, "canonical Cure-All or PandorasBox ID is unavailable before reclaim");
			return;
		}
		int reclaimIncrement = UsagePolicy.GetReclaimIncrement(itemID, id, id2);
		bool flag = false;
		try
		{
			Player.localPlayer.EmptySlot(currentSelectedSlot, true);
			flag = true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Limited reclaim failed while emptying slot " + currentSelectedSlot.Value + ": " + ex.Message));
			return;
		}
		_reclaimAttemptedInstances.Add(instanceID);
		try
		{
			((MonoBehaviourPun)items).photonView.RPC("DestroyHeldItemRpc", (RpcTarget)0, Array.Empty<object>());
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Limited reclaim partially failed after EmptySlot for item instance " + instanceID + ": " + ex2.Message));
			return;
		}
		if (!flag || (Object)(object)localCharacter.data.currentItem != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Limited reclaim partially failed for item instance " + instanceID + ": the local held item did not detach."));
			return;
		}
		try
		{
			items.EquipSlot(Optionable<byte>.None);
		}
		catch (Exception ex3)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Limited reclaim detached item instance " + instanceID + " but failed to refresh the empty selected slot: " + ex3.Message));
		}
		if (_remainingUsage.TryGetValue(itemID, out var value2))
		{
			int value3 = UsagePolicy.AddReclaimReward(value2, itemID, id, id2);
			_remainingUsage[itemID] = value3;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Limited reclaim itemId=" + itemID + " increment=" + reclaimIncrement + " result=" + value3 + " canonicalCureAll=" + id + " canonicalPandorasBox=" + id2));
			InvalidateCustomWheelState();
		}
	}

	private void LogReclaimValidation(int instanceId, string reason)
	{
		if (_reclaimValidationLogged.Add(instanceId))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Limited reclaim rejected for item instance " + instanceId + ": " + reason + "."));
		}
	}

	private bool TryGetCanonicalItemId(ushort itemId)
	{
		EnsureUsageCounts();
		return _remainingUsage.ContainsKey(itemId);
	}

	private static void CharacterStartPrefix(Character __instance, ref bool __state)
	{
		__state = (Object)(object)_instance != (Object)null && (Object)(object)__instance != (Object)null && !_instance.ReadBoolMember(__instance, "started", fallback: false);
	}

	private static void CharacterStartPostfix(Character __instance, bool __state)
	{
		if (!((Object)(object)_instance == (Object)null) && __state && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Character.localCharacter) && !((Object)(object)((MonoBehaviourPun)__instance).photonView == (Object)null) && ((MonoBehaviourPun)__instance).photonView.IsMine && _instance.ReadBoolMember(__instance, "started", fallback: false))
		{
			_instance.ResetAllUsageCounts();
		}
	}

	private static void StartRunPostfix()
	{
		if (!((Object)(object)_instance == (Object)null))
		{
			_instance.ResetAllUsageCounts();
			_instance._stageRewardTracker.StartNewRun();
			((BaseUnityPlugin)_instance).Logger.LogInfo((object)"Stage observer reset for NEW RUN.");
		}
	}

	private static void SetSegmentOnSpawnPrefix()
	{
		if ((Object)(object)_instance != (Object)null)
		{
			_instance._segmentSpawnSyncDepth++;
		}
	}

	private static Exception SetSegmentOnSpawnFinalizer(Exception __exception)
	{
		if ((Object)(object)_instance != (Object)null)
		{
			_instance._segmentSpawnSyncDepth = Mathf.Max(0, _instance._segmentSpawnSyncDepth - 1);
			_instance._stageRebaselinePending = true;
		}
		return __exception;
	}

	private static void ReviveCharacterPrefix(Character __instance, ref bool __state)
	{
		__state = (Object)(object)_instance != (Object)null && (Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)Character.localCharacter && (Object)(object)__instance.data != (Object)null && __instance.data.dead;
	}

	private static void ReviveCharacterPostfix(Character __instance, bool __state)
	{
		if (Object.op_Implicit((Object)(object)_instance) && __state && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Character.localCharacter) && !((Object)(object)__instance.data == (Object)null) && !__instance.data.dead)
		{
			_instance.ResetAllUsageCounts();
		}
	}

	private ConfigEntry<string> BindTriggerMode(string key, string defaultValue)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Expected O, but got Unknown
		return ((BaseUnityPlugin)this).Config.Bind<string>("Trigger Modes", key, defaultValue, new ConfigDescription("该物品的 Ping 触发路径;Cooking 使用原版 ItemCooking.Explode,Collision 只使用物品原版碰撞组件。 / Per-item Ping path; Cooking uses vanilla ItemCooking.Explode, Collision uses only the item’s vanilla collision component.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Cooking", "Collision" }), Array.Empty<object>()));
	}

	private void TryOpenCustomWheel()
	{
		Character localCharacter = Character.localCharacter;
		GUIManager instance = GUIManager.instance;
		if (!_enabled.Value || !Application.isFocused || !PhotonNetwork.InRoom || !IsLocalVanillaPingOwner(localCharacter) || !NativeWheelReferencesReady(instance) || instance.wheelActive || instance.windowBlockingInput || !ResolveWheelItems(out var entries))
		{
			return;
		}
		EmoteWheel componentInChildren = instance.emoteWheel.GetComponentInChildren<EmoteWheel>(true);
		if ((Object)(object)componentInChildren == (Object)null || componentInChildren.slices == null || componentInChildren.slices.Length == 0)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"The vanilla EmoteWheel prefab or its slices is unavailable.");
			return;
		}
		GameObject val = Object.Instantiate<GameObject>(instance.emoteWheel, instance.emoteWheel.transform.parent);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		val.SetActive(false);
		try
		{
			_customWheelObject = val;
			_customMarker = val.GetComponent<CustomWheelMarker>() ?? val.AddComponent<CustomWheelMarker>();
			_customMarker.Owner = this;
			_customWheel = val.GetComponentInChildren<EmoteWheel>(true);
			if ((Object)(object)_customWheel == (Object)null)
			{
				throw new InvalidOperationException("The cloned vanilla EmoteWheel component is unavailable.");
			}
			if (entries.Count > 8)
			{
				entries = entries.GetRange(0, 8);
			}
			_wheelItems = entries;
			_wheelDataRebuildPending = !_canonicalUsageIdsResolved;
			_customWheel.data = CreateWheelData(entries, Mathf.Max(8, componentInChildren.slices.Length));
			_customWheel.pages = 1;
			if ((Object)(object)_customWheel.nextButton != (Object)null)
			{
				((Component)_customWheel.nextButton).gameObject.SetActive(false);
			}
			if ((Object)(object)_customWheel.prevButton != (Object)null)
			{
				((Component)_customWheel.prevButton).gameObject.SetActive(false);
			}
			if (_emoteWheelPage != null)
			{
				_emoteWheelPage.SetValue(_customWheel, 0);
			}
			_previousUsingEmoteWheel = localCharacter.data.usingEmoteWheel;
			_wheelCharacter = localCharacter;
			_wheelCharacterData = localCharacter.data;
			_wheelCharacterData.usingEmoteWheel = true;
			_customWheelActive = true;
			_closingWheel = false;
			val.SetActive(true);
			CreateCountLabels();
			InvalidateCustomWheelState();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to initialize the item wheel: " + ex));
			AbortCustomWheel();
		}
	}

	private void UpdateCustomWheel()
	{
		if (!IsWheelInteractionAuthorized())
		{
			AbortCustomWheel();
			return;
		}
		ItemEntry selectedItem = GetSelectedItem();
		if (selectedItem != null && !CanUseItem(selectedItem.ItemId))
		{
			ClearSelectedData();
		}
		if (!Input.GetKey((KeyCode)122))
		{
			ItemEntry selectedItem2 = GetSelectedItem();
			bool num = selectedItem2 != null && CanUseItem(selectedItem2.ItemId);
			CloseCustomWheel();
			if (num)
			{
				PersistSelectedItem(selectedItem2.Token);
			}
		}
	}

	private bool IsWheelInteractionAuthorized()
	{
		Character localCharacter = Character.localCharacter;
		GUIManager instance = GUIManager.instance;
		if (_enabled.Value && Application.isFocused && PhotonNetwork.InRoom && _customWheelActive && IsLocalVanillaPingOwner(localCharacter) && (Object)(object)localCharacter == (Object)(object)_wheelCharacter && (Object)(object)localCharacter.data == (Object)(object)_wheelCharacterData && NativeWheelReferencesReady(instance) && !instance.windowBlockingInput && !instance.emoteWheel.activeSelf && !((Component)instance.backpackWheel).gameObject.activeSelf && (Object)(object)_customWheelObject != (Object)null)
		{
			return (Object)(object)_customWheel != (Object)null;
		}
		return false;
	}

	private void PersistSelectedItem(string token)
	{
		if (string.IsNullOrEmpty(token))
		{
			return;
		}
		try
		{
			_item.Value = token;
			((BaseUnityPlugin)this).Config.Save();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Next Ping item set to '" + token + "'."));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to persist General/Item='" + token + "': " + ex));
		}
	}

	private bool TryResolveConfiguredItem(out Item item, out string prefabName)
	{
		item = null;
		prefabName = null;
		string effectiveItemToken = GetEffectiveItemToken();
		try
		{
			if (!ItemDatabase.TryGetItem(effectiveItemToken, ref item) || (Object)(object)item == (Object)null)
			{
				List<Item> list = FindSimplifiedChineseMatches(effectiveItemToken);
				if (list.Count == 1)
				{
					item = list[0];
				}
				else if (list.Count > 1)
				{
					LogValidationError("Item token '" + effectiveItemToken + "' matches multiple Simplified Chinese localized items; spawn rejected.");
					return false;
				}
			}
		}
		catch (Exception ex)
		{
			LogValidationError("ItemDatabase lookup failed for '" + effectiveItemToken + "': " + ex.Message);
			return false;
		}
		if ((Object)(object)item == (Object)null)
		{
			LogValidationError("Item '" + effectiveItemToken + "' could not be resolved by prefab name or unique Simplified Chinese localized name.");
			return false;
		}
		prefabName = (((Object)(object)((Component)item).gameObject != (Object)null) ? ((Object)((Component)item).gameObject).name : ((Object)item).name);
		if (string.IsNullOrEmpty(prefabName))
		{
			LogValidationError("Resolved item '" + effectiveItemToken + "' has no prefab name.");
			return false;
		}
		return true;
	}

	private string GetEffectiveItemToken()
	{
		if (_item != null && _item.Value != null)
		{
			return _item.Value.Trim();
		}
		return string.Empty;
	}

	private bool TryValidateCookingPrefab(Item prefab, string prefabName, out ItemCooking cooking)
	{
		cooking = (((Object)(object)prefab == (Object)null) ? null : ((Component)prefab).GetComponent<ItemCooking>());
		if ((Object)(object)cooking == (Object)null)
		{
			LogValidationError("Cooking rejected for '" + prefabName + "': prefab has no ItemCooking component.");
			return false;
		}
		if ((Object)(object)cooking.explosionPrefab == (Object)null)
		{
			LogValidationError("Cooking rejected for '" + prefabName + "': ItemCooking.explosionPrefab is null.");
			return false;
		}
		return true;
	}

	private string GetTriggerMode(Item prefab, string prefabName, string itemToken)
	{
		if (IsWarpFungus(prefab, prefabName, itemToken))
		{
			return _warpFungusMode.Value;
		}
		if (IsShelfMushroom(prefab, itemToken))
		{
			return _stepMushroomMode.Value;
		}
		if (IsHealingPuffShroom(prefab, prefabName, itemToken))
		{
			return _elixirMushroomMode.Value;
		}
		if (string.Equals(prefabName, "Cure-All", StringComparison.Ordinal))
		{
			return _cureAllMode.Value;
		}
		if (string.Equals(prefabName, "Dynamite", StringComparison.Ordinal))
		{
			return _dynamiteMode.Value;
		}
		if (string.Equals(prefabName, "AntiZooka", StringComparison.Ordinal))
		{
			return _antiZookaMode.Value;
		}
		if (string.Equals(prefabName, "PandorasBox", StringComparison.Ordinal))
		{
			return _pandorasBoxMode.Value;
		}
		LogValidationError("No per-item trigger mode is configured for resolved prefab '" + prefabName + "'; spawn rejected without fallback.");
		return null;
	}

	private bool IsFrisbee(Item prefab, string prefabName, string itemToken)
	{
		if (!string.Equals(prefabName, "Frisbee", StringComparison.OrdinalIgnoreCase) && !string.Equals(itemToken, "Frisbee", StringComparison.OrdinalIgnoreCase))
		{
			if ((Object)(object)prefab != (Object)null)
			{
				return string.Equals(((Object)prefab).name, "Frisbee", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}
		return true;
	}

	private bool TryValidateCollisionPrefab(Item prefab, string prefabName, string itemToken, out CollisionKind kind)
	{
		kind = CollisionKind.None;
		Component val = FindComponent(prefab, "WarpOnThrow");
		Component val2 = FindComponent(prefab, "Breakable");
		Component obj = FindComponent(prefab, "ShelfShroom");
		ShelfShroom val3 = (ShelfShroom)(object)((obj is ShelfShroom) ? obj : null);
		if (IsWarpFungus(prefab, prefabName, itemToken))
		{
			if ((Object)(object)val != (Object)null)
			{
				kind = CollisionKind.WarpOnThrow;
			}
			else
			{
				LogValidationError("Collision rejected for WarpFungus: WarpOnThrow is missing; Breakable is not used as a fallback.");
			}
		}
		else if ((Object)(object)val3 != (Object)null && val3.breakOnCollision && (Object)(object)val3.instantiateOnBreak != (Object)null && IsFiniteNonNegative(val3.minBreakVelocity))
		{
			kind = CollisionKind.ShelfShroom;
		}
		else if ((Object)(object)val2 != (Object)null && ReadBoolMember(val2, "breakOnCollision", fallback: false))
		{
			kind = CollisionKind.Breakable;
		}
		else if ((Object)(object)val != (Object)null)
		{
			kind = CollisionKind.WarpOnThrow;
		}
		else if (IsHealingPuffShroom(prefab, prefabName, itemToken))
		{
			kind = CollisionKind.HealingPuffShroom;
			((BaseUnityPlugin)this).Logger.LogWarning((object)"HealingPuffShroom has no supported native collision trigger in this game build; using a generic physical launch with no guaranteed healing effect, then cleaning up the original item.");
		}
		if (kind == CollisionKind.None)
		{
			LogValidationError("Collision rejected for '" + prefabName + "': runtime prefab has no supported Breakable, ShelfShroom, WarpOnThrow, or HealingPuffShroom path. No cooking fallback is used.");
			if (string.Equals(prefabName, "Cure-All", StringComparison.Ordinal))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Cure-All was not identified as a supported collision prefab; its actual runtime component is not assumed.");
			}
			return false;
		}
		return true;
	}

	private bool IsWarpFungus(Item prefab, string prefabName, string itemToken)
	{
		if (string.Equals(prefabName, "WarpFungus", StringComparison.Ordinal) || string.Equals(itemToken, "WarpFungus", StringComparison.Ordinal))
		{
			return true;
		}
		return IsSimplifiedChineseItem(prefab, itemToken, "曲迁菇");
	}

	private bool IsShelfMushroom(Item prefab, string itemToken)
	{
		if (!string.Equals(itemToken, "踏板菇", StringComparison.Ordinal) && !((Object)(object)FindComponent(prefab, "ShelfShroom") != (Object)null))
		{
			return IsSimplifiedChineseItem(prefab, itemToken, "踏板菇");
		}
		return true;
	}

	private bool IsHealingPuffShroom(Item prefab, string prefabName, string itemToken)
	{
		if (!string.Equals(prefabName, "HealingPuffShroom", StringComparison.Ordinal) && !string.Equals(itemToken, "HealingPuffShroom", StringComparison.Ordinal))
		{
			return IsSimplifiedChineseItem(prefab, itemToken, "灵药菇");
		}
		return true;
	}

	private bool IsFiniteNonNegative(float value)
	{
		if (!float.IsNaN(value) && !float.IsInfinity(value))
		{
			return value >= 0f;
		}
		return false;
	}

	private bool IsTerrainCollider(Collider collider)
	{
		if ((Object)(object)collider != (Object)null)
		{
			return IsTerrainLayer(((Component)collider).gameObject.layer);
		}
		return false;
	}

	private bool IsTerrainLayer(int layer)
	{
		if (layer >= 0 && layer < 32)
		{
			return (((LayerMask)(ref HelperFunctions.terrainMapMask)).value & (1 << layer)) != 0;
		}
		return false;
	}

	private bool IsSimplifiedChineseItem(Item prefab, string itemToken, string expectedName)
	{
		if (string.Equals(itemToken, expectedName, StringComparison.Ordinal))
		{
			return true;
		}
		if ((Object)(object)prefab == (Object)null || prefab.UIData == null || string.IsNullOrEmpty(prefab.UIData.itemName))
		{
			return false;
		}
		try
		{
			return string.Equals(LocalizedText.GetText(LocalizedText.GetNameIndex(prefab.UIData.itemName), (Language)9), expectedName, StringComparison.Ordinal);
		}
		catch
		{
			return false;
		}
	}

	private bool SpawnCookingItem(Item prefab, string prefabName, Vector3 position, ItemCooking cooking)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = InstantiateNetworkItem(prefabName, position);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		ChargeSuccessfulSpawn(prefab.itemID, prefabName);
		try
		{
			((MonoBehaviour)this).StartCoroutine(InitializeAndExplode(val, prefabName, cooking.explosionPrefab));
			return true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to start cooking initialization for '" + prefabName + "': " + ex));
			DestroySpawnedItemIfOwner(val, val.GetComponent<PhotonView>());
			return false;
		}
	}

	private void SpawnCollisionItem(Character local, Item prefab, string prefabName, RaycastHit hit, CollisionKind kind)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: 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_002f: Unknown result type (might be due to invalid IL or missing references)
		Vector3 terrainClearanceSpawnPosition = GetTerrainClearanceSpawnPosition(prefab, hit);
		GameObject val = InstantiateNetworkItem(prefabName, terrainClearanceSpawnPosition);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		ChargeSuccessfulSpawn(prefab.itemID, prefabName);
		try
		{
			((MonoBehaviour)this).StartCoroutine(InitializeCollisionItem(val, prefabName, local, hit, kind));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to start collision initialization for '" + prefabName + "': " + ex));
			DestroySpawnedItemIfOwner(val, val.GetComponent<PhotonView>());
		}
	}

	private void SpawnFrisbee(Character local, Item prefab, string prefabName, RaycastHit hit)
	{
		//IL_0022: 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_014c: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: 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)
		if (!TryGetFrisbeeSettings(out var searchRadius, out var speed, out var lifetime))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Frisbee rejected: Throw settings are not finite or usable.");
			return;
		}
		if (!TryFindFrisbeeTarget(((RaycastHit)(ref hit)).point, local, searchRadius, out var target, out var error))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Frisbee rejected: " + error));
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Frisbee target selected: type=" + target.TargetType + ", display='" + target.DisplayName + "', collider='" + ((Object)target.Collider).name + "', layer=" + ((Component)target.Collider).gameObject.layer + "."));
		ArrowShooter componentInParent = ((Component)target.Collider).GetComponentInParent<ArrowShooter>();
		bool flag = (Object)(object)componentInParent != (Object)null;
		if (!TryCreateFrisbeeGeometry(((Object)(object)prefab == (Object)null) ? null : ((Component)prefab).gameObject, out var geometry, out var error2))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)((flag ? "Frisbee ArrowShooter [structure] prefab geometry rejected: " : "Frisbee rejected: ") + error2));
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Frisbee geometry: " + DescribeFrisbeeGeometry(geometry) + "."));
		FrisbeePingSnapshot ping = new FrisbeePingSnapshot(((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal, ((RaycastHit)(ref hit)).collider);
		bool flag2;
		Vector3 position;
		Quaternion rotation;
		string error3;
		string route;
		try
		{
			flag2 = TryPrepareFrisbeeRoute(ping, target.Collider, local, geometry, null, null, flag, componentInParent, searchRadius, out var _, out position, out var _, out var _, out rotation, out error3, out route);
		}
		finally
		{
			DestroyFrisbeeGeometry(geometry);
		}
		if (!flag2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Frisbee rejected: " + error3 + " Geometry