Decompiled source of Simple Multi Player v1.7.3

WKMultiPlayerMod.dll

Decompiled 2 days ago
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DG.Tweening;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Steamworks;
using Steamworks.Data;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using WKMPMod.Asset;
using WKMPMod.Component;
using WKMPMod.Core;
using WKMPMod.Data;
using WKMPMod.MK_Component;
using WKMPMod.NetWork;
using WKMPMod.Patch;
using WKMPMod.RemotePlayer;
using WKMPMod.UI;
using WKMPMod.Util;
using WKMPMod.World;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WKMultiPlayerMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.7.3.0")]
[assembly: AssemblyInformationalVersion("1.7.3+b98d64200e307c3673484e728fc0fe1c77208fc9")]
[assembly: AssemblyProduct("WKMultiPlayerMod")]
[assembly: AssemblyTitle("WKMultiPlayerMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.7.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public abstract class Singleton<T> where T : Singleton<T>
{
	private static readonly Lazy<T> _instance = new Lazy<T>(CreateInstance, isThreadSafe: true);

	public static T Instance => _instance.Value;

	public static bool IsCreated => _instance.IsValueCreated;

	private static T CreateInstance()
	{
		try
		{
			ConstructorInfo constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (constructor == null)
			{
				throw new InvalidOperationException("Singleton<" + typeof(T).Name + ">: Type must have a parameterless constructor");
			}
			return (T)constructor.Invoke(null);
		}
		catch (Exception innerException)
		{
			throw new InvalidOperationException("Singleton<" + typeof(T).Name + ">: Failed to create instance", innerException);
		}
	}

	protected Singleton()
	{
		if (_instance.IsValueCreated)
		{
			throw new InvalidOperationException("Singleton<" + typeof(T).Name + ">: Instance already exists. Use " + typeof(T).Name + ".Instance instead.");
		}
	}
}
namespace WKMPMod.World
{
	public enum PitonSyncAction : byte
	{
		Create,
		Update,
		Remove
	}
	public static class ClimbableItemSyncManager
	{
		private const float PeriodicUpdateInterval = 0.15f;

		private const float PositionEpsilonSqr = 0.0004f;

		private const float RotationEpsilon = 0.5f;

		private const float SecureAmountEpsilon = 0.01f;

		private static List<GameObject> CapturedPitons = new List<GameObject>();

		private static readonly FieldRef<Projectile, GameEntity> _projectileSourceEntityField = AccessTools.FieldRefAccess<Projectile, GameEntity>("sourceEntity");

		private static readonly Dictionary<string, NetworkedClimableItem> _pitons = new Dictionary<string, NetworkedClimableItem>();

		private static ulong _nextLocalId = 1uL;

		public static bool ApplyingRemoteState { get; private set; }

		public static void SaveCapturedPiton(GameObject go)
		{
			if ((Object)(object)go != (Object)null && (Object)(object)go.GetComponentInChildren<CL_Handhold>(true) != (Object)null)
			{
				CapturedPitons.Add(go);
			}
		}

		public static void RegisterNewLocalPiton(HandItem_Piton source)
		{
			if (!MPCore.CanSync || ApplyingRemoteState || (Object)(object)source == (Object)null || CapturedPitons.Count == 0)
			{
				CapturedPitons.Clear();
				return;
			}
			foreach (GameObject capturedPiton in CapturedPitons)
			{
				GameObject climbableRoot = GetClimbableRoot(capturedPiton);
				if (!((Object)(object)climbableRoot == (Object)null))
				{
					RegisterLocalClimbable(climbableRoot, ((Object)source.pitonWorldObject).name);
				}
			}
			CapturedPitons.Clear();
		}

		public static void RegisterNewLocalProjectileClimbable(Projectile source, RaycastHit hit)
		{
			if (!MPCore.CanSync || ApplyingRemoteState || (Object)(object)source == (Object)null || !IsLocalProjectile(source))
			{
				CapturedPitons.Clear();
				return;
			}
			foreach (GameObject capturedPiton in CapturedPitons)
			{
				GameObject climbableRoot = GetClimbableRoot(capturedPiton);
				if (!((Object)(object)climbableRoot == (Object)null))
				{
					RegisterLocalClimbable(climbableRoot, ((Object)(object)climbableRoot != (Object)null) ? ((Object)climbableRoot).name : ((Object)((Component)source).gameObject).name);
				}
			}
			CapturedPitons.Clear();
		}

		public static void BroadcastHammerUpdate(CL_Handhold handhold)
		{
			if (MPCore.CanSync && !ApplyingRemoteState && !((Object)(object)handhold == (Object)null))
			{
				NetworkedClimableItem networkedClimableItem = FindIdentity(handhold);
				if (!((Object)(object)networkedClimableItem == (Object)null) && !string.IsNullOrEmpty(networkedClimableItem.NetworkId))
				{
					Broadcast(networkedClimableItem, PitonSyncAction.Update, force: true);
				}
			}
		}

		public static void BroadcastPeriodicUpdate(CL_Handhold handhold)
		{
			if (!MPCore.CanSync || ApplyingRemoteState || (Object)(object)handhold == (Object)null)
			{
				return;
			}
			NetworkedClimableItem networkedClimableItem = FindIdentity(handhold);
			if ((Object)(object)networkedClimableItem == (Object)null || string.IsNullOrEmpty(networkedClimableItem.NetworkId))
			{
				return;
			}
			if (!((Component)networkedClimableItem).gameObject.activeSelf)
			{
				Broadcast(networkedClimableItem, PitonSyncAction.Remove, force: true);
			}
			else if (!(Time.time - networkedClimableItem.LastSentTime < 0.15f))
			{
				CL_Handhold trackedHandhold = GetTrackedHandhold(((Component)networkedClimableItem).gameObject);
				if (HasMeaningfulStateChange(networkedClimableItem, trackedHandhold))
				{
					Broadcast(networkedClimableItem, PitonSyncAction.Update, force: false);
				}
			}
		}

		public static void HandlePitonState(ulong senderId, DataReader reader)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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)
			PitonSyncAction pitonSyncAction = (PitonSyncAction)reader.GetByte();
			string text = reader.GetString();
			string prefabKey = reader.GetString();
			Vector3 vector = reader.GetVector3();
			Quaternion quaternion = reader.GetQuaternion();
			float secureAmount = reader.GetFloat();
			bool secure = reader.GetBool();
			bool active = reader.GetBool();
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			ApplyingRemoteState = true;
			try
			{
				switch (pitonSyncAction)
				{
				case PitonSyncAction.Create:
					ApplyCreate(senderId, text, prefabKey, vector, quaternion, secureAmount, secure, active);
					break;
				case PitonSyncAction.Update:
					ApplyUpdate(text, vector, quaternion, secureAmount, secure, active);
					break;
				case PitonSyncAction.Remove:
					ApplyRemove(text);
					break;
				}
			}
			catch (Exception ex)
			{
				MPMain.LogError($"[MP ClimbableSync] Failed to apply {pitonSyncAction} for {text}: {ex.Message}");
			}
			finally
			{
				ApplyingRemoteState = false;
			}
		}

		private static void RegisterLocalClimbable(GameObject root, string prefabKey)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			string text = MPUtil.CleanCloneName(prefabKey);
			if (!string.IsNullOrEmpty(text))
			{
				NetworkedClimableItem orCreateIdentity = GetOrCreateIdentity(root);
				if (string.IsNullOrEmpty(orCreateIdentity.NetworkId))
				{
					orCreateIdentity.NetworkId = $"{MPSteamworks.UserSteamId}:{_nextLocalId++}";
					orCreateIdentity.OwnerId = MPSteamworks.UserSteamId;
					orCreateIdentity.IsRemote = false;
				}
				orCreateIdentity.PrefabKey = text;
				_pitons[orCreateIdentity.NetworkId] = orCreateIdentity;
				Broadcast(orCreateIdentity, PitonSyncAction.Create, force: true);
			}
		}

		private static void ApplyCreate(ulong senderId, string networkId, string prefabKey, Vector3 position, Quaternion rotation, float secureAmount, bool secure, bool active)
		{
			//IL_002e: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (_pitons.TryGetValue(networkId, out NetworkedClimableItem value) && (Object)(object)value != (Object)null)
			{
				value.PrefabKey = MPUtil.CleanCloneName(prefabKey);
				ApplyState(value, position, rotation, secureAmount, secure, active);
				return;
			}
			GameObject handholdPrefab = MPAssetManager.GetHandholdPrefab(prefabKey);
			if ((Object)(object)handholdPrefab == (Object)null)
			{
				MPMain.LogError("[MP ClimbableSync] Could not resolve prefab '" + prefabKey + "' for " + networkId + ".");
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(handholdPrefab, position, rotation);
			Transform currentLevelParentRoot = WorldLoader.GetCurrentLevelParentRoot();
			if ((Object)(object)currentLevelParentRoot != (Object)null)
			{
				val.transform.SetParent(currentLevelParentRoot);
			}
			TryAddPlacedObjectToLevel(val);
			NetworkedClimableItem orCreateIdentity = GetOrCreateIdentity(val);
			orCreateIdentity.NetworkId = networkId;
			orCreateIdentity.PrefabKey = MPUtil.CleanCloneName(prefabKey);
			orCreateIdentity.OwnerId = senderId;
			orCreateIdentity.IsRemote = true;
			_pitons[networkId] = orCreateIdentity;
			ApplyState(orCreateIdentity, position, rotation, secureAmount, secure, active);
		}

		private static void ApplyUpdate(string networkId, Vector3 position, Quaternion rotation, float secureAmount, bool secure, bool active)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (_pitons.TryGetValue(networkId, out NetworkedClimableItem value) && !((Object)(object)value == (Object)null))
			{
				ApplyState(value, position, rotation, secureAmount, secure, active);
			}
		}

		private static void ApplyRemove(string networkId)
		{
			if (_pitons.TryGetValue(networkId, out NetworkedClimableItem value) && !((Object)(object)value == (Object)null))
			{
				if ((Object)(object)((Component)value).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
				_pitons.Remove(networkId);
			}
		}

		private static void ApplyState(NetworkedClimableItem identity, Vector3 position, Quaternion rotation, float secureAmount, bool secure, bool active)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)identity).transform;
			transform.position = position;
			transform.rotation = rotation;
			CL_Handhold trackedHandhold = GetTrackedHandhold(((Component)identity).gameObject);
			if ((Object)(object)trackedHandhold != (Object)null)
			{
				trackedHandhold.Initialize();
				trackedHandhold.secureAmount = secureAmount;
				trackedHandhold.secure = secure;
			}
			((Component)identity).gameObject.SetActive(active);
			RecordState(identity, trackedHandhold);
		}

		private static GameObject GetClimbableRoot(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return null;
			}
			Transform val = (WorldLoader.initialized ? WorldLoader.GetCurrentLevelParentRoot() : null);
			Transform val2 = obj.transform;
			while ((Object)(object)val2.parent != (Object)null && (Object)(object)val2.parent != (Object)(object)val)
			{
				val2 = val2.parent;
			}
			return ((Component)val2).gameObject;
		}

		private static CL_Handhold GetTrackedHandhold(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			return root.GetComponent<CL_Handhold>() ?? root.GetComponentInChildren<CL_Handhold>(true);
		}

		private static NetworkedClimableItem FindIdentity(CL_Handhold handhold)
		{
			return ((Component)handhold).GetComponent<NetworkedClimableItem>() ?? ((Component)handhold).GetComponentInParent<NetworkedClimableItem>();
		}

		private static bool IsLocalProjectile(Projectile projectile)
		{
			ENT_Player player = ENT_Player.GetPlayer();
			if ((Object)(object)projectile == (Object)null || (Object)(object)player == (Object)null || _projectileSourceEntityField == null)
			{
				return false;
			}
			GameEntity val = _projectileSourceEntityField.Invoke(projectile);
			return (Object)(object)val == (Object)(object)player;
		}

		private static void TryAddPlacedObjectToLevel(GameObject climbableObject)
		{
			if (!WorldLoader.initialized || (Object)(object)climbableObject == (Object)null)
			{
				return;
			}
			try
			{
				M_Level level = WorldLoader.instance.GetCurrentLevel().GetLevel();
				typeof(M_Level).GetMethod("AddPlacedObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(level, new object[1] { climbableObject });
			}
			catch (Exception ex)
			{
				MPMain.LogWarning("[MP ClimbableSync] Could not register remote climbable as placed object: " + ex.Message);
			}
		}

		private static NetworkedClimableItem GetOrCreateIdentity(GameObject obj)
		{
			NetworkedClimableItem networkedClimableItem = obj.GetComponent<NetworkedClimableItem>();
			if ((Object)(object)networkedClimableItem == (Object)null)
			{
				networkedClimableItem = obj.AddComponent<NetworkedClimableItem>();
			}
			return networkedClimableItem;
		}

		private static void Broadcast(NetworkedClimableItem identity, PitonSyncAction action, bool force)
		{
			//IL_006e: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)identity == (Object)null || string.IsNullOrEmpty(identity.NetworkId))
			{
				return;
			}
			CL_Handhold trackedHandhold = GetTrackedHandhold(((Component)identity).gameObject);
			DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, 0uL, PacketType.PitonStateSync);
			writer.Put((byte)action);
			writer.Put(identity.NetworkId);
			writer.Put(identity.PrefabKey ?? string.Empty);
			writer.Put(((Component)identity).transform.position);
			writer.Put(((Component)identity).transform.rotation);
			writer.Put(((Object)(object)trackedHandhold != (Object)null) ? trackedHandhold.secureAmount : 0f);
			writer.Put((Object)(object)trackedHandhold != (Object)null && trackedHandhold.secure);
			writer.Put(((Component)identity).gameObject.activeSelf);
			if (action == PitonSyncAction.Create || action == PitonSyncAction.Remove)
			{
				MonoSingleton<MPSteamworks>.Instance.Broadcast(writer, (SendType)8, 0);
			}
			else if (action == PitonSyncAction.Update)
			{
				foreach (ulong item in MonoSingleton<LocalPlayer>.Instance._nearPlayersBuffer)
				{
					MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(item), writer, (SendType)0, 0);
				}
			}
			RecordState(identity, trackedHandhold);
			if (force)
			{
				MPMain.LogInfo($"[MP ClimbableSync] Sent {action} for {identity.NetworkId} ({identity.PrefabKey})");
			}
		}

		private static bool HasMeaningfulStateChange(NetworkedClimableItem identity, CL_Handhold handhold)
		{
			//IL_0023: 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_0038: 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: Unknown result type (might be due to invalid IL or missing references)
			if (identity.LastActive != ((Component)identity).gameObject.activeSelf)
			{
				return true;
			}
			Vector3 val = identity.LastPosition - ((Component)identity).transform.position;
			if (((Vector3)(ref val)).sqrMagnitude > 0.0004f)
			{
				return true;
			}
			if (Quaternion.Angle(identity.LastRotation, ((Component)identity).transform.rotation) > 0.5f)
			{
				return true;
			}
			if ((Object)(object)handhold == (Object)null)
			{
				return false;
			}
			if (Mathf.Abs(identity.LastSecureAmount - handhold.secureAmount) > 0.01f)
			{
				return true;
			}
			return identity.LastSecure != handhold.secure;
		}

		private static void RecordState(NetworkedClimableItem identity, CL_Handhold handhold)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			identity.LastSentTime = Time.time;
			identity.LastPosition = ((Component)identity).transform.position;
			identity.LastRotation = ((Component)identity).transform.rotation;
			identity.LastActive = ((Component)identity).gameObject.activeSelf;
			if ((Object)(object)handhold != (Object)null)
			{
				identity.LastSecureAmount = handhold.secureAmount;
				identity.LastSecure = handhold.secure;
			}
		}
	}
	public enum ItemSyncAction : byte
	{
		SnapshotReset,
		SnapshotFinalize,
		Create,
		PickupRequest,
		DropRequest,
		Remove
	}
	public static class ItemSyncManager
	{
		private sealed class PendingLocalDrop
		{
			public Item_Object ItemObject { get; }

			public string PrefabKey { get; }

			public float CreatedAt { get; }

			public PendingLocalDrop(Item_Object itemObject, string prefabKey, float createdAt)
			{
				ItemObject = itemObject;
				PrefabKey = prefabKey;
				CreatedAt = createdAt;
			}
		}

		private const float CandidateMatchDistanceSqr = 0.5f;

		private const float LocalDropMatchDistanceSqr = 25f;

		private const float LocalDropMaxAge = 3f;

		private const float LocalDropPickupSuppressWindow = 0.2f;

		private const float VelocityEpsilonSqr = 0.0025f;

		private const float WorldReadyTimeout = 12f;

		private const float StableIdPositionPrecision = 20f;

		private const float StableIdRotationPrecision = 5f;

		private const int SnapshotItemsPerFrame = 10;

		private static readonly FieldRef<Item, Item_Object> _dropObjectField = AccessTools.FieldRefAccess<Item, Item_Object>("dropObject");

		private static readonly Dictionary<string, NetworkedItem> _items = new Dictionary<string, NetworkedItem>();

		private static readonly List<Item_Object> _clientCandidates = new List<Item_Object>();

		private static readonly List<PendingLocalDrop> _pendingLocalDrops = new List<PendingLocalDrop>();

		private static readonly List<Item_Object> _snapshotCandidates = new List<Item_Object>();

		private static readonly Dictionary<ulong, Coroutine> _snapshotRoutines = new Dictionary<ulong, Coroutine>();

		private static readonly Dictionary<int, float> _suppressedPickupObjects = new Dictionary<int, float>();

		private static ulong _nextHostItemId = 1uL;

		private static Coroutine _prepareRoutine;

		private static Coroutine _hostDiscoveryRoutine;

		private static bool _hostSceneItemsRegistered;

		private static readonly HashSet<string> _blacklistedPrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Item_Flashlight", "Item_Flaregun", "Item_Cryogun" };

		private static readonly HashSet<string> _blacklistedItemTags = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "artifact", "disk" };

		public static bool ApplyingRemoteState { get; private set; }

		public static void NotifyWorldInitialized()
		{
			ResetState();
			if ((Object)(object)MonoSingleton<MPCore>.Instance == (Object)null)
			{
				MPMain.LogWarning("[MP ItemSync] Prepare skipped: MPCore.Instance is null.");
			}
			else
			{
				_prepareRoutine = ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StartCoroutine(PrepareWorldRoutine());
			}
		}

		public static void ResetState()
		{
			if (_prepareRoutine != null && (Object)(object)MonoSingleton<MPCore>.Instance != (Object)null)
			{
				((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(_prepareRoutine);
				_prepareRoutine = null;
			}
			if (_hostDiscoveryRoutine != null && (Object)(object)MonoSingleton<MPCore>.Instance != (Object)null)
			{
				((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(_hostDiscoveryRoutine);
				_hostDiscoveryRoutine = null;
			}
			if ((Object)(object)MonoSingleton<MPCore>.Instance != (Object)null)
			{
				foreach (Coroutine value in _snapshotRoutines.Values)
				{
					if (value != null)
					{
						((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(value);
					}
				}
			}
			_snapshotRoutines.Clear();
			foreach (NetworkedItem value2 in _items.Values)
			{
				if (!((Object)(object)value2 == (Object)null) && !((Object)(object)((Component)value2).gameObject == (Object)null) && value2.WasInstantiatedBySync)
				{
					Object.Destroy((Object)(object)((Component)value2).gameObject);
				}
			}
			_items.Clear();
			_clientCandidates.Clear();
			_pendingLocalDrops.Clear();
			_snapshotCandidates.Clear();
			_suppressedPickupObjects.Clear();
			_hostSceneItemsRegistered = false;
			ApplyingRemoteState = false;
			MPMain.LogInfo("[MP ItemSync] ResetState completed.");
		}

		public static void SendSnapshotToClient(ulong clientId)
		{
			if (MPCore.CanSync && MonoSingleton<MPSteamworks>.Instance.IsHost && !((Object)(object)MonoSingleton<MPCore>.Instance == (Object)null) && clientId != 0L && clientId != MPSteamworks.UserSteamId)
			{
				if (_snapshotRoutines.TryGetValue(clientId, out Coroutine value) && value != null)
				{
					((MonoBehaviour)MonoSingleton<MPCore>.Instance).StopCoroutine(value);
				}
				_snapshotRoutines[clientId] = ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StartCoroutine(SendSnapshotToClientRoutine(clientId));
			}
		}

		public static void NotifyLocalPickup(Item_Object itemObject)
		{
			if (ApplyingRemoteState || (Object)(object)itemObject == (Object)null || !MPCore.CanSync)
			{
				return;
			}
			if (IsPendingLocalDrop(itemObject))
			{
				MPMain.LogInfo("[MP ItemSync] Suppressed pickup for pending local drop. Item=" + ((Object)itemObject).name);
			}
			else
			{
				if (ShouldSuppressLocalPickup(itemObject))
				{
					return;
				}
				NetworkedItem component = ((Component)itemObject).GetComponent<NetworkedItem>();
				if ((Object)(object)component == (Object)null || string.IsNullOrEmpty(component.NetworkId))
				{
					MPMain.LogWarning("[MP ItemSync] Pickup ignored: missing NetworkedItem or NetworkId. Item=" + ((Object)itemObject).name + ", PrefabKey=" + GetPrefabKey(itemObject) + ", " + $"HasIdentity={(Object)(object)component != (Object)null}");
					return;
				}
				MPMain.LogInfo("[MP ItemSync] Local pickup. " + $"Host={MonoSingleton<MPSteamworks>.Instance.IsHost}, " + "Item=" + ((Object)itemObject).name + ", NetworkId=" + component.NetworkId + ", PrefabKey=" + component.PrefabKey);
				if (MonoSingleton<MPSteamworks>.Instance.IsHost)
				{
					BroadcastRemove(component.NetworkId);
					Forget(component.NetworkId);
				}
				else
				{
					SendPickupRequest(component.NetworkId);
				}
			}
		}

		public static void NotifyLocalDrop(Item item)
		{
			//IL_0108: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (ApplyingRemoteState || item == null || !MPCore.CanSync)
			{
				return;
			}
			Item_Object val = _dropObjectField.Invoke(item);
			if (!IsSyncableWorldItem(val))
			{
				return;
			}
			string prefabKey = GetPrefabKey(val);
			if (!string.IsNullOrEmpty(prefabKey))
			{
				if (MonoSingleton<MPSteamworks>.Instance.IsHost)
				{
					NetworkedItem networkedItem = RegisterHostItem(val, prefabKey);
					Vector3 velocity = GetVelocity(val);
					RememberSuppressedPickup(val);
					MPMain.LogInfo("[MP ItemSync] Host local drop. Item=" + ((Object)val).name + ", NetworkId=" + networkedItem.NetworkId + ", PrefabKey=" + prefabKey);
					BroadcastCreate(networkedItem, val, velocity, isDropSpawn: true);
				}
				else
				{
					RememberCandidate(val, snapshotCandidate: false);
					RememberPendingLocalDrop(val, prefabKey);
					RememberSuppressedPickup(val);
					MPMain.LogInfo("[MP ItemSync] Client local drop request. Item=" + ((Object)val).name + ", PrefabKey=" + prefabKey);
					SendDropRequest(prefabKey, ((Component)val).transform.position, ((Component)val).transform.rotation, GetVelocity(val));
				}
			}
		}

		public static void SpawnSyncedWorldDrop(string prefabKey, Vector3 position, Quaternion rotation, Vector3 velocity)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_003f: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (ApplyingRemoteState || !MPCore.CanSync || string.IsNullOrWhiteSpace(prefabKey))
			{
				return;
			}
			if (!MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				SendDropRequest(prefabKey, position, rotation, velocity);
				return;
			}
			Item_Object val = InstantiateWorldItem(prefabKey, position, rotation);
			if ((Object)(object)val == (Object)null)
			{
				MPMain.LogWarning("[MP ItemSync] Could not instantiate synced drop '" + prefabKey + "'.");
				return;
			}
			NetworkedItem identity = RegisterHostItem(val, prefabKey);
			RememberSuppressedPickup(val);
			ApplyCreate(identity, position, rotation, velocity, isDropSpawn: true, skipDropCallbacks: false);
			BroadcastCreate(identity, val, velocity, isDropSpawn: true);
		}

		public static void HandleItemState(ulong senderId, DataReader reader)
		{
			ItemSyncAction itemSyncAction = (ItemSyncAction)reader.GetByte();
			try
			{
				switch (itemSyncAction)
				{
				case ItemSyncAction.SnapshotReset:
					HandleSnapshotReset();
					break;
				case ItemSyncAction.SnapshotFinalize:
					HandleSnapshotFinalize();
					break;
				case ItemSyncAction.Create:
					HandleCreate(senderId, reader);
					break;
				case ItemSyncAction.PickupRequest:
					HandlePickupRequest(reader);
					break;
				case ItemSyncAction.DropRequest:
					HandleDropRequest(senderId, reader);
					break;
				case ItemSyncAction.Remove:
					HandleRemove(reader);
					break;
				}
			}
			catch (Exception ex)
			{
				MPMain.LogError($"[MP ItemSync] Failed to apply {itemSyncAction}: {ex.Message}");
			}
		}

		private static IEnumerator PrepareWorldRoutine()
		{
			MPMain.LogInfo("[MP ItemSync] PrepareWorldRoutine started. " + $"IsHost={MonoSingleton<MPSteamworks>.Instance.IsHost}, IsInLobby={MPCore.IsInLobby}, CanSync={MPCore.CanSync}, " + $"WorldInitialized={WorldLoader.initialized}, WorldLoaded={WorldLoader.isLoaded}");
			yield return WaitForWorldReady();
			yield return null;
			yield return null;
			if (MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				yield return RegisterHostSceneItemsRoutine();
				if ((Object)(object)MonoSingleton<MPCore>.Instance != (Object)null && _hostDiscoveryRoutine == null)
				{
					_hostDiscoveryRoutine = ((MonoBehaviour)MonoSingleton<MPCore>.Instance).StartCoroutine(HostDiscoveryRoutine());
				}
			}
			else if (MPCore.IsInLobby)
			{
				CaptureSceneCandidates(snapshotCandidate: true);
				MPMain.LogInfo("[MP ItemSync] Captured client scene candidates. " + $"Candidates={_clientCandidates.Count}, SnapshotCandidates={_snapshotCandidates.Count}");
			}
			else
			{
				MPMain.LogInfo("[MP ItemSync] Prepare skipped candidate capture because client is not in lobby.");
			}
			_prepareRoutine = null;
			MPMain.LogInfo("[MP ItemSync] PrepareWorldRoutine finished. " + $"Items={_items.Count}, HostSceneItemsRegistered={_hostSceneItemsRegistered}");
		}

		private static IEnumerator SendSnapshotToClientRoutine(ulong clientId)
		{
			yield return WaitForWorldReady();
			if (!_hostSceneItemsRegistered)
			{
				yield return RegisterHostSceneItemsRoutine();
			}
			SendSnapshotReset(clientId);
			List<NetworkedItem> snapshot = new List<NetworkedItem>(EnumerateKnownHostWorldItems());
			int sentThisFrame = 0;
			foreach (NetworkedItem identity in snapshot)
			{
				if ((Object)(object)identity == (Object)null || (Object)(object)((Component)identity).gameObject == (Object)null)
				{
					continue;
				}
				Item_Object itemObject = ((Component)identity).GetComponent<Item_Object>();
				if (IsSyncableWorldItem(itemObject))
				{
					SendCreate(clientId, identity, itemObject, GetVelocity(itemObject), isDropSpawn: false);
					sentThisFrame++;
					if (sentThisFrame >= 10)
					{
						sentThisFrame = 0;
						yield return null;
					}
				}
			}
			SendSnapshotFinalize(clientId);
			_snapshotRoutines.Remove(clientId);
			MPMain.LogInfo($"[MP ItemSync] Sent item snapshot to {clientId}. Items={snapshot.Count}");
		}

		private static IEnumerator WaitForWorldReady()
		{
			float elapsed = 0f;
			while ((!WorldLoader.initialized || !WorldLoader.isLoaded) && elapsed < 12f)
			{
				elapsed += Time.unscaledDeltaTime;
				yield return null;
			}
			MPMain.LogInfo("[MP ItemSync] World ready wait finished. " + $"Elapsed={elapsed:F2}, Initialized={WorldLoader.initialized}, Loaded={WorldLoader.isLoaded}");
		}

		private static IEnumerator RegisterHostSceneItemsRoutine()
		{
			if (!MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				yield break;
			}
			int registeredThisFrame = 0;
			int totalRegistered = 0;
			foreach (Item_Object itemObject in EnumerateSceneItems())
			{
				string prefabKey = GetPrefabKey(itemObject);
				if (!string.IsNullOrEmpty(prefabKey))
				{
					RegisterHostItem(itemObject, prefabKey, preferStableSceneIdentity: true);
					totalRegistered++;
					registeredThisFrame++;
					if (registeredThisFrame >= 10)
					{
						registeredThisFrame = 0;
						yield return null;
					}
				}
			}
			_hostSceneItemsRegistered = true;
			MPMain.LogInfo($"[MP ItemSync] Registered host scene items. Items={totalRegistered}");
		}

		private static IEnumerator HostDiscoveryRoutine()
		{
			WaitForSecondsRealtime wait = new WaitForSecondsRealtime(0.5f);
			while ((Object)(object)MonoSingleton<MPCore>.Instance != (Object)null)
			{
				if (MPCore.CanSync && MonoSingleton<MPSteamworks>.Instance.IsHost && _hostSceneItemsRegistered)
				{
					DiscoverAndBroadcastNewHostWorldItems();
				}
				yield return wait;
			}
			_hostDiscoveryRoutine = null;
		}

		private static void DiscoverAndBroadcastNewHostWorldItems()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			foreach (Item_Object item in EnumerateSceneItems())
			{
				if (TryPrepareNewHostWorldItem(item, out string prefabKey))
				{
					NetworkedItem networkedItem = RegisterHostItem(item, prefabKey, preferStableSceneIdentity: true);
					RememberSuppressedPickup(item);
					MPMain.LogInfo("[MP ItemSync] Registered dynamic host world item. Item=" + ((Object)item).name + ", NetworkId=" + networkedItem.NetworkId + ", PrefabKey=" + prefabKey);
					BroadcastCreate(networkedItem, item, GetVelocity(item), isDropSpawn: false);
				}
			}
		}

		private static bool TryPrepareNewHostWorldItem(Item_Object itemObject, out string prefabKey)
		{
			prefabKey = string.Empty;
			if (!IsSyncableWorldItem(itemObject))
			{
				return false;
			}
			prefabKey = GetPrefabKey(itemObject);
			if (string.IsNullOrEmpty(prefabKey))
			{
				return false;
			}
			NetworkedItem component = ((Component)itemObject).GetComponent<NetworkedItem>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			if (string.IsNullOrEmpty(component.NetworkId))
			{
				return true;
			}
			return !_items.ContainsKey(component.NetworkId);
		}

		private static IEnumerable<NetworkedItem> EnumerateKnownHostWorldItems()
		{
			foreach (NetworkedItem identity in _items.Values)
			{
				if (!((Object)(object)identity == (Object)null) && !((Object)(object)((Component)identity).gameObject == (Object)null))
				{
					Item_Object itemObject = ((Component)identity).GetComponent<Item_Object>();
					if (IsSyncableWorldItem(itemObject))
					{
						yield return identity;
					}
				}
			}
		}

		private static NetworkedItem RegisterHostItem(Item_Object itemObject, string prefabKey, bool preferStableSceneIdentity = false)
		{
			NetworkedItem orCreateIdentity = GetOrCreateIdentity(((Component)itemObject).gameObject);
			if (preferStableSceneIdentity)
			{
				TryAssignStableSceneIdentity(itemObject, orCreateIdentity);
			}
			if (string.IsNullOrEmpty(orCreateIdentity.NetworkId))
			{
				orCreateIdentity.NetworkId = $"{MPSteamworks.UserSteamId}:item:{_nextHostItemId++}";
			}
			orCreateIdentity.PrefabKey = prefabKey;
			orCreateIdentity.OwnerId = MPSteamworks.UserSteamId;
			orCreateIdentity.IsRemote = false;
			orCreateIdentity.WasInstantiatedBySync = false;
			if (_items.TryGetValue(orCreateIdentity.NetworkId, out NetworkedItem value) && (Object)(object)value != (Object)null && (Object)(object)value != (Object)(object)orCreateIdentity)
			{
				MPMain.LogWarning("[MP ItemSync] Duplicate NetworkId detected. NetworkId=" + orCreateIdentity.NetworkId + ", Existing=" + ((Object)value).name + ", New=" + ((Object)itemObject).name);
			}
			_items[orCreateIdentity.NetworkId] = orCreateIdentity;
			return orCreateIdentity;
		}

		private static void HandleSnapshotReset()
		{
			if (!MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				MPMain.LogInfo("[MP ItemSync] Received snapshot reset.");
				ResetState();
				CaptureSceneCandidates(snapshotCandidate: true);
			}
		}

		private static void HandleSnapshotFinalize()
		{
			if (MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				return;
			}
			int num = 0;
			for (int num2 = _snapshotCandidates.Count - 1; num2 >= 0; num2--)
			{
				Item_Object val = _snapshotCandidates[num2];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					NetworkedItem component = ((Component)val).GetComponent<NetworkedItem>();
					if (!((Object)(object)component != (Object)null) || string.IsNullOrEmpty(component.NetworkId) || !_items.ContainsKey(component.NetworkId))
					{
						((Component)val).gameObject.SetActive(false);
						num++;
					}
				}
			}
			_snapshotCandidates.Clear();
			MPMain.LogInfo($"[MP ItemSync] Snapshot finalized. Hidden unmatched scene items={num}.");
		}

		private static void HandleCreate(ulong senderId, DataReader reader)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_0116: 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_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			if (MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				return;
			}
			string text = reader.GetString();
			string text2 = reader.GetString();
			Vector3 vector = reader.GetVector3();
			Quaternion quaternion = reader.GetQuaternion();
			Vector3 vector2 = reader.GetVector3();
			bool flag = reader.GetBool();
			if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2))
			{
				return;
			}
			if (_items.TryGetValue(text, out NetworkedItem value) && (Object)(object)value != (Object)null)
			{
				ApplyCreate(value, vector, quaternion, vector2, flag, skipDropCallbacks: true);
				return;
			}
			Item_Object val = (flag ? FindPendingLocalDrop(text2, vector) : null);
			bool wasSnapshotCandidate = false;
			if ((Object)(object)val == (Object)null)
			{
				val = FindSceneItemByStableId(text);
				if ((Object)(object)val != (Object)null)
				{
					wasSnapshotCandidate = _snapshotCandidates.Contains(val);
					RemoveCandidate(val);
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = FindClientCandidate(text2, vector, out wasSnapshotCandidate);
			}
			Item_Object val2 = val;
			bool wasInstantiatedBySync = false;
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = InstantiateWorldItem(text2, vector, quaternion);
				wasInstantiatedBySync = (Object)(object)val2 != (Object)null;
			}
			if ((Object)(object)val2 == (Object)null)
			{
				MPMain.LogWarning("[MP ItemSync] Could not create item '" + text2 + "' for " + text + ".");
				return;
			}
			NetworkedItem orCreateIdentity = GetOrCreateIdentity(((Component)val2).gameObject);
			if (text.StartsWith("sceneitem:", StringComparison.Ordinal))
			{
				orCreateIdentity.StableSceneId = text;
			}
			orCreateIdentity.NetworkId = text;
			orCreateIdentity.PrefabKey = text2;
			orCreateIdentity.OwnerId = senderId;
			orCreateIdentity.IsRemote = true;
			orCreateIdentity.WasInstantiatedBySync = wasInstantiatedBySync;
			if (_items.TryGetValue(text, out NetworkedItem value2) && (Object)(object)value2 != (Object)null && (Object)(object)value2 != (Object)(object)orCreateIdentity)
			{
				MPMain.LogWarning("[MP ItemSync] Duplicate client NetworkId detected on create. NetworkId=" + text + ", Existing=" + ((Object)value2).name + ", New=" + ((Object)val2).name);
			}
			_items[text] = orCreateIdentity;
			bool skipDropCallbacks = !wasSnapshotCandidate && (Object)(object)val != (Object)null && flag;
			ApplyCreate(orCreateIdentity, vector, quaternion, vector2, flag, skipDropCallbacks);
		}

		private static void HandlePickupRequest(DataReader reader)
		{
			if (!MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				return;
			}
			string text = reader.GetString();
			MPMain.LogInfo("[MP ItemSync] Host received pickup request. NetworkId=" + text);
			if (!string.IsNullOrEmpty(text))
			{
				if (!_items.ContainsKey(text))
				{
					MPMain.LogWarning("[MP ItemSync] Pickup request ignored. Unknown NetworkId=" + text);
					return;
				}
				BroadcastRemove(text);
				Forget(text);
			}
		}

		private static void HandleDropRequest(ulong senderId, DataReader reader)
		{
			//IL_0021: 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_0028: 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_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_0047: 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_00cd: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (!MonoSingleton<MPSteamworks>.Instance.IsHost)
			{
				return;
			}
			string text = reader.GetString();
			Vector3 vector = reader.GetVector3();
			Quaternion quaternion = reader.GetQuaternion();
			Vector3 vector2 = reader.GetVector3();
			if (!string.IsNullOrEmpty(text))
			{
				Item_Object val = InstantiateWorldItem(text, vector, quaternion);
				if ((Object)(object)val == (Object)null)
				{
					MPMain.LogWarning("[MP ItemSync] Could not instantiate dropped item '" + text + "'.");
					return;
				}
				NetworkedItem networkedItem = RegisterHostItem(val, text);
				networkedItem.OwnerId = senderId;
				MPMain.LogInfo("[MP ItemSync] Host accepted drop request. " + $"Sender={senderId}, Item={((Object)val).name}, NetworkId={networkedItem.NetworkId}, PrefabKey={text}");
				ApplyCreate(networkedItem, vector, quaternion, vector2, isDropSpawn: true, skipDropCallbacks: false);
				BroadcastCreate(networkedItem, val, vector2, isDropSpawn: true);
			}
		}

		private static void HandleRemove(DataReader reader)
		{
			string text = reader.GetString();
			MPMain.LogInfo("[MP ItemSync] Received remove. NetworkId=" + text);
			if (!string.IsNullOrEmpty(text))
			{
				Forget(text);
			}
		}

		private static void ApplyCreate(NetworkedItem identity, Vector3 position, Quaternion rotation, Vector3 velocity, bool isDropSpawn, bool skipDropCallbacks)
		{
			//IL_0030: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)identity == (Object)null || (Object)(object)((Component)identity).gameObject == (Object)null)
			{
				return;
			}
			ApplyingRemoteState = true;
			try
			{
				((Component)identity).transform.position = position;
				((Component)identity).transform.rotation = rotation;
				Item_Object component = ((Component)identity).GetComponent<Item_Object>();
				if ((Object)(object)component != (Object)null && component.itemData != null)
				{
					_dropObjectField.Invoke(component.itemData) = component;
				}
				if (isDropSpawn && (Object)(object)component != (Object)null && !skipDropCallbacks)
				{
					component.OnDrop();
				}
				Rigidbody rigidbody = GetRigidbody(((Component)identity).gameObject);
				if ((Object)(object)rigidbody != (Object)null)
				{
					rigidbody.isKinematic = false;
					rigidbody.velocity = velocity;
				}
				((Component)identity).gameObject.SetActive(true);
			}
			finally
			{
				ApplyingRemoteState = false;
			}
		}

		private static void Forget(string networkId)
		{
			if (!_items.TryGetValue(networkId, out NetworkedItem value) || (Object)(object)value == (Object)null)
			{
				if (!TryForgetUnknownSceneItem(networkId))
				{
					MPMain.LogWarning("[MP ItemSync] Forget ignored. Unknown NetworkId=" + networkId);
				}
				return;
			}
			Item_Object component = ((Component)value).GetComponent<Item_Object>();
			if ((Object)(object)component != (Object)null)
			{
				RemoveCandidate(component);
			}
			MPMain.LogInfo("[MP ItemSync] Forget item. NetworkId=" + networkId + ", Item=" + (((Object)(object)((Component)value).gameObject != (Object)null) ? ((Object)((Component)value).gameObject).name : "null") + ", " + $"WasInstantiatedBySync={value.WasInstantiatedBySync}");
			if ((Object)(object)((Component)value).gameObject != (Object)null)
			{
				((Component)value).gameObject.SetActive(false);
				if (value.WasInstantiatedBySync)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
			_items.Remove(networkId);
		}

		private static bool TryForgetUnknownSceneItem(string networkId)
		{
			if (string.IsNullOrEmpty(networkId))
			{
				return false;
			}
			if (!networkId.StartsWith("sceneitem:", StringComparison.Ordinal))
			{
				return false;
			}
			Item_Object val = FindSceneItemByStableId(networkId);
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
			{
				return false;
			}
			NetworkedItem component = ((Component)val).GetComponent<NetworkedItem>();
			if ((Object)(object)component != (Object)null && string.IsNullOrEmpty(component.NetworkId))
			{
				component.NetworkId = networkId;
				component.StableSceneId = networkId;
			}
			RemoveCandidate(val);
			((Component)val).gameObject.SetActive(false);
			_items.Remove(networkId);
			MPMain.LogWarning("[MP ItemSync] Forgot unknown scene item by stable ID fallback. NetworkId=" + networkId + ", Item=" + ((Object)val).name);
			return true;
		}

		private static void SendSnapshotReset(ulong clientId)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, clientId, PacketType.ItemStateSync);
			writer.Put((byte)0);
			MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(clientId), writer, (SendType)8, 0);
		}

		private static void SendSnapshotFinalize(ulong clientId)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, clientId, PacketType.ItemStateSync);
			writer.Put((byte)1);
			MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(clientId), writer, (SendType)8, 0);
		}

		private static void SendCreate(ulong clientId, NetworkedItem identity, Item_Object itemObject, Vector3 velocity, bool isDropSpawn)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)identity == (Object)null) && !((Object)(object)itemObject == (Object)null) && !string.IsNullOrEmpty(identity.NetworkId))
			{
				DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, clientId, PacketType.ItemStateSync);
				writer.Put((byte)2);
				writer.Put(identity.NetworkId);
				writer.Put(identity.PrefabKey);
				writer.Put(((Component)itemObject).transform.position);
				writer.Put(((Component)itemObject).transform.rotation);
				writer.Put(velocity);
				writer.Put(isDropSpawn);
				MonoSingleton<MPSteamworks>.Instance.SendToPeer(SteamId.op_Implicit(clientId), writer, (SendType)8, 0);
			}
		}

		private static void BroadcastCreate(NetworkedItem identity, Item_Object itemObject, Vector3 velocity, bool isDropSpawn)
		{
			//IL_005f: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)identity == (Object)null) && !((Object)(object)itemObject == (Object)null) && !string.IsNullOrEmpty(identity.NetworkId))
			{
				DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, 0uL, PacketType.ItemStateSync);
				writer.Put((byte)2);
				writer.Put(identity.NetworkId);
				writer.Put(identity.PrefabKey);
				writer.Put(((Component)itemObject).transform.position);
				writer.Put(((Component)itemObject).transform.rotation);
				writer.Put(velocity);
				writer.Put(isDropSpawn);
				MonoSingleton<MPSteamworks>.Instance.Broadcast(writer, (SendType)8, 0);
			}
		}

		private static void BroadcastRemove(string networkId)
		{
			DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, 0uL, PacketType.ItemStateSync);
			writer.Put((byte)5);
			writer.Put(networkId);
			MPMain.LogInfo("[MP ItemSync] Broadcast remove. NetworkId=" + networkId);
			MonoSingleton<MPSteamworks>.Instance.Broadcast(writer, (SendType)8, 0);
		}

		private static void SendPickupRequest(string networkId)
		{
			DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, MonoSingleton<MPSteamworks>.Instance.HostSteamId, PacketType.ItemStateSync);
			writer.Put((byte)3);
			writer.Put(networkId);
			MPMain.LogInfo("[MP ItemSync] Sent pickup request. NetworkId=" + networkId);
			MonoSingleton<MPSteamworks>.Instance.SendToHost(writer, (SendType)8, 0);
		}

		private static void SendDropRequest(string prefabKey, Vector3 position, Quaternion rotation, Vector3 velocity)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)
			DataWriter writer = MPWriterPool.GetWriter(MPSteamworks.UserSteamId, MonoSingleton<MPSteamworks>.Instance.HostSteamId, PacketType.ItemStateSync);
			writer.Put((byte)4);
			writer.Put(prefabKey);
			writer.Put(position);
			writer.Put(rotation);
			writer.Put(velocity);
			MonoSingleton<MPSteamworks>.Instance.SendToHost(writer, (SendType)8, 0);
		}

		private static void CaptureSceneCandidates(bool snapshotCandidate)
		{
			foreach (Item_Object item in EnumerateSceneItems())
			{
				RememberCandidate(item, snapshotCandidate);
			}
		}

		private static IEnumerable<Item_Object> EnumerateSceneItems()
		{
			Item_Object[] array = Object.FindObjectsOfType<Item_Object>();
			foreach (Item_Object itemObject in array)
			{
				if (IsSyncableWorldItem(itemObject) && !IsBlacklisted(itemObject))
				{
					yield return itemObject;
				}
			}
		}

		private static void RememberCandidate(Item_Object itemObject, bool snapshotCandidate)
		{
			if (!IsSyncableWorldItem(itemObject))
			{
				return;
			}
			NetworkedItem orCreateIdentity = GetOrCreateIdentity(((Component)itemObject).gameObject);
			if (snapshotCandidate && TryAssignStableSceneIdentity(itemObject, orCreateIdentity))
			{
				orCreateIdentity.PrefabKey = GetPrefabKey(itemObject);
				if (_items.TryGetValue(orCreateIdentity.NetworkId, out NetworkedItem value) && (Object)(object)value != (Object)null && (Object)(object)value != (Object)(object)orCreateIdentity)
				{
					MPMain.LogWarning("[MP ItemSync] Duplicate client candidate NetworkId detected. NetworkId=" + orCreateIdentity.NetworkId + ", Existing=" + ((Object)value).name + ", New=" + ((Object)itemObject).name);
				}
				_items[orCreateIdentity.NetworkId] = orCreateIdentity;
			}
			else if (!string.IsNullOrEmpty(orCreateIdentity.NetworkId))
			{
				if (_items.TryGetValue(orCreateIdentity.NetworkId, out NetworkedItem value2) && (Object)(object)value2 != (Object)null && (Object)(object)value2 != (Object)(object)orCreateIdentity)
				{
					MPMain.LogWarning("[MP ItemSync] Duplicate remembered NetworkId detected. NetworkId=" + orCreateIdentity.NetworkId + ", Existing=" + ((Object)value2).name + ", New=" + ((Object)itemObject).name);
				}
				_items[orCreateIdentity.NetworkId] = orCreateIdentity;
			}
			else
			{
				if (!_clientCandidates.Contains(itemObject))
				{
					_clientCandidates.Add(itemObject);
				}
				if (snapshotCandidate && !_snapshotCandidates.Contains(itemObject))
				{
					_snapshotCandidates.Add(itemObject);
				}
			}
		}

		private static void RemoveCandidate(Item_Object itemObject)
		{
			_clientCandidates.Remove(itemObject);
			_snapshotCandidates.Remove(itemObject);
			RemovePendingLocalDrop(itemObject);
		}

		private static Item_Object FindClientCandidate(string prefabKey, Vector3 position, out bool wasSnapshotCandidate)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			RemoveDestroyedCandidates();
			Item_Object val = null;
			float num = float.MaxValue;
			wasSnapshotCandidate = false;
			foreach (Item_Object clientCandidate in _clientCandidates)
			{
				if (IsSyncableWorldItem(clientCandidate) && PrefabKeysMatch(prefabKey, GetPrefabKey(clientCandidate)))
				{
					Vector3 val2 = ((Component)clientCandidate).transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (!(sqrMagnitude > 0.5f) && !(sqrMagnitude >= num))
					{
						val = clientCandidate;
						num = sqrMagnitude;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				wasSnapshotCandidate = _snapshotCandidates.Contains(val);
				RemoveCandidate(val);
			}
			return val;
		}

		private static void RememberPendingLocalDrop(Item_Object itemObject, string prefabKey)
		{
			if (IsSyncableWorldItem(itemObject) && !string.IsNullOrEmpty(prefabKey))
			{
				RemoveDestroyedPendingLocalDrops();
				RemovePendingLocalDrop(itemObject);
				_pendingLocalDrops.Add(new PendingLocalDrop(itemObject, prefabKey, Time.time));
			}
		}

		private static Item_Object FindPendingLocalDrop(string prefabKey, Vector3 position)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			RemoveDestroyedPendingLocalDrops();
			Item_Object val = null;
			float num = float.MaxValue;
			for (int num2 = _pendingLocalDrops.Count - 1; num2 >= 0; num2--)
			{
				PendingLocalDrop pendingLocalDrop = _pendingLocalDrops[num2];
				if (PrefabKeysMatch(prefabKey, pendingLocalDrop.PrefabKey))
				{
					Vector3 val2 = ((Component)pendingLocalDrop.ItemObject).transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (!(sqrMagnitude > 25f) && !(sqrMagnitude >= num))
					{
						val = pendingLocalDrop.ItemObject;
						num = sqrMagnitude;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				RemoveCandidate(val);
			}
			return val;
		}

		private static bool IsPendingLocalDrop(Item_Object itemObject)
		{
			if ((Object)(object)itemObject == (Object)null)
			{
				return false;
			}
			RemoveDestroyedPendingLocalDrops();
			for (int i = 0; i < _pendingLocalDrops.Count; i++)
			{
				if ((Object)(object)_pendingLocalDrops[i].ItemObject == (Object)(object)itemObject)
				{
					return true;
				}
			}
			return false;
		}

		private static void RemovePendingLocalDrop(Item_Object itemObject)
		{
			if ((Object)(object)itemObject == (Object)null)
			{
				return;
			}
			for (int num = _pendingLocalDrops.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)_pendingLocalDrops[num].ItemObject == (Object)(object)itemObject)
				{
					_pendingLocalDrops.RemoveAt(num);
				}
			}
		}

		private static void RemoveDestroyedCandidates()
		{
			for (int num = _clientCandidates.Count - 1; num >= 0; num--)
			{
				if (!IsSyncableWorldItem(_clientCandidates[num]))
				{
					_clientCandidates.RemoveAt(num);
				}
			}
			for (int num2 = _snapshotCandidates.Count - 1; num2 >= 0; num2--)
			{
				if (!IsSyncableWorldItem(_snapshotCandidates[num2]))
				{
					_snapshotCandidates.RemoveAt(num2);
				}
			}
			RemoveDestroyedPendingLocalDrops();
		}

		private static void RemoveDestroyedPendingLocalDrops()
		{
			float num = Time.time - 3f;
			for (int num2 = _pendingLocalDrops.Count - 1; num2 >= 0; num2--)
			{
				PendingLocalDrop pendingLocalDrop = _pendingLocalDrops[num2];
				if (!IsSyncableWorldItem(pendingLocalDrop.ItemObject) || pendingLocalDrop.CreatedAt < num)
				{
					_pendingLocalDrops.RemoveAt(num2);
				}
			}
		}

		private static void RememberSuppressedPickup(Item_Object itemObject)
		{
			if (!((Object)(object)itemObject == (Object)null) && !((Object)(object)((Component)itemObject).gameObject == (Object)null))
			{
				RemoveExpiredSuppressedPickups();
				_suppressedPickupObjects[((Object)((Component)itemObject).gameObject).GetInstanceID()] = Time.time + 0.2f;
			}
		}

		private static bool ShouldSuppressLocalPickup(Item_Object itemObject)
		{
			if ((Object)(object)itemObject == (Object)null || (Object)(object)((Component)itemObject).gameObject == (Object)null)
			{
				return false;
			}
			RemoveExpiredSuppressedPickups();
			int instanceID = ((Object)((Component)itemObject).gameObject).GetInstanceID();
			if (!_suppressedPickupObjects.TryGetValue(instanceID, out var value))
			{
				return false;
			}
			if (Time.time > value)
			{
				_suppressedPickupObjects.Remove(instanceID);
				return false;
			}
			MPMain.LogInfo("[MP ItemSync] Suppressed pickup immediately after drop. Item=" + ((Object)itemObject).name);
			return true;
		}

		private static void RemoveExpiredSuppressedPickups()
		{
			if (_suppressedPickupObjects.Count == 0)
			{
				return;
			}
			foreach (int item in new List<int>(_suppressedPickupObjects.Keys))
			{
				if (_suppressedPickupObjects.TryGetValue(item, out var value) && Time.time > value)
				{
					_suppressedPickupObjects.Remove(item);
				}
			}
		}

		private static bool IsSyncableWorldItem(Item_Object itemObject)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)itemObject == (Object)null || (Object)(object)((Component)itemObject).gameObject == (Object)null)
			{
				return false;
			}
			if (!((Component)itemObject).gameObject.activeInHierarchy)
			{
				return false;
			}
			Scene scene = ((Component)itemObject).gameObject.scene;
			if (string.IsNullOrEmpty(((Scene)(ref scene)).name))
			{
				return false;
			}
			if (itemObject.itemData == null)
			{
				return false;
			}
			if (itemObject.itemData.inBag)
			{
				return false;
			}
			return true;
		}

		private static Item_Object InstantiateWorldItem(string prefabKey, Vector3 position, Quaternion rotation)
		{
			//IL_0028: 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)
			GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(prefabKey, "");
			if ((Object)(object)assetGameObject == (Object)null)
			{
				return null;
			}
			ApplyingRemoteState = true;
			try
			{
				GameObject val = Object.Instantiate<GameObject>(assetGameObject, position, rotation);
				Transform currentLevelParentRoot = WorldLoader.GetCurrentLevelParentRoot();
				if ((Object)(object)currentLevelParentRoot != (Object)null)
				{
					val.transform.SetParent(currentLevelParentRoot);
				}
				Item_Object val2 = val.GetComponent<Item_Object>() ?? val.GetComponentInChildren<Item_Object>(true);
				if ((Object)(object)val2 != (Object)null && val2.itemData != null)
				{
					val2.itemData.InitializeItemData(val2);
				}
				return val2;
			}
			finally
			{
				ApplyingRemoteState = false;
			}
		}

		private static Vector3 GetVelocity(Item_Object itemObject)
		{
			//IL_0021: 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_0018: 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_003d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody rigidbody = GetRigidbody(((Component)itemObject).gameObject);
			if ((Object)(object)rigidbody == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 velocity = rigidbody.velocity;
			return (((Vector3)(ref velocity)).sqrMagnitude > 0.0025f) ? rigidbody.velocity : Vector3.zero;
		}

		private static Rigidbody GetRigidbody(GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return null;
			}
			return gameObject.GetComponent<Rigidbody>() ?? gameObject.GetComponentInChildren<Rigidbody>();
		}

		private static NetworkedItem GetOrCreateIdentity(GameObject gameObject)
		{
			NetworkedItem networkedItem = gameObject.GetComponent<NetworkedItem>();
			if ((Object)(object)networkedItem == (Object)null)
			{
				networkedItem = gameObject.AddComponent<NetworkedItem>();
			}
			return networkedItem;
		}

		private static Item_Object FindSceneItemByStableId(string networkId)
		{
			if (string.IsNullOrEmpty(networkId) || !networkId.StartsWith("sceneitem:", StringComparison.Ordinal))
			{
				return null;
			}
			foreach (Item_Object item in EnumerateSceneItems())
			{
				if (string.Equals(GetStableSceneItemId(item), networkId, StringComparison.Ordinal))
				{
					return item;
				}
			}
			return null;
		}

		private static bool TryAssignStableSceneIdentity(Item_Object itemObject, NetworkedItem identity)
		{
			if ((Object)(object)itemObject == (Object)null || (Object)(object)identity == (Object)null)
			{
				return false;
			}
			string stableSceneItemId = GetStableSceneItemId(itemObject);
			if (string.IsNullOrEmpty(stableSceneItemId))
			{
				return false;
			}
			identity.StableSceneId = stableSceneItemId;
			identity.NetworkId = stableSceneItemId;
			return true;
		}

		private static string GetStableSceneItemId(Item_Object itemObject)
		{
			//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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)itemObject == (Object)null || (Object)(object)((Component)itemObject).gameObject == (Object)null)
			{
				return string.Empty;
			}
			Scene scene = ((Component)itemObject).gameObject.scene;
			if (((Scene)(ref scene)).IsValid())
			{
				scene = ((Component)itemObject).gameObject.scene;
				if (!string.IsNullOrEmpty(((Scene)(ref scene)).name))
				{
					NetworkedItem component = ((Component)itemObject).GetComponent<NetworkedItem>();
					if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.StableSceneId))
					{
						return component.StableSceneId;
					}
					string text = BuildTransformPath(((Component)itemObject).transform);
					if (string.IsNullOrEmpty(text))
					{
						return string.Empty;
					}
					string text2 = BuildStableTransformAnchor(((Component)itemObject).transform);
					string[] obj = new string[6] { "sceneitem:", null, null, null, null, null };
					scene = ((Component)itemObject).gameObject.scene;
					obj[1] = ((Scene)(ref scene)).name;
					obj[2] = ":";
					obj[3] = text;
					obj[4] = "|";
					obj[5] = text2;
					return string.Concat(obj);
				}
			}
			return string.Empty;
		}

		private static string BuildTransformPath(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder();
			Stack<string> stack = new Stack<string>();
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				stack.Push($"{MPUtil.CleanCloneName(((Object)val).name)}[{val.GetSiblingIndex()}]");
				val = val.parent;
			}
			while (stack.Count > 0)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append('/');
				}
				stringBuilder.Append(stack.Pop());
			}
			return stringBuilder.ToString();
		}

		private static string BuildStableTransformAnchor(Transform transform)
		{
			//IL_0018: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0076: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)transform == (Object)null)
			{
				return string.Empty;
			}
			Vector3 localPosition = transform.localPosition;
			Vector3 localEulerAngles = transform.localEulerAngles;
			return $"lp:{Quantize(localPosition.x, 20f)}," + $"{Quantize(localPosition.y, 20f)}," + $"{Quantize(localPosition.z, 20f)}" + $"|lr:{Quantize(NormalizeAngle(localEulerAngles.x), 5f)}," + $"{Quantize(NormalizeAngle(localEulerAngles.y), 5f)}," + $"{Quantize(NormalizeAngle(localEulerAngles.z), 5f)}";
		}

		private static int Quantize(float value, float precision)
		{
			return Mathf.RoundToInt(value * precision);
		}

		private static float NormalizeAngle(float value)
		{
			value %= 360f;
			if (value < 0f)
			{
				value += 360f;
			}
			return value;
		}

		private static string GetPrefabKey(Item_Object itemObject)
		{
			if ((Object)(object)itemObject == (Object)null)
			{
				return string.Empty;
			}
			if (itemObject.itemData != null && !string.IsNullOrEmpty(itemObject.itemData.prefabName))
			{
				return itemObject.itemData.prefabName;
			}
			return MPUtil.CleanCloneName(((Object)((Component)itemObject).gameObject).name);
		}

		private static bool PrefabKeysMatch(string a, string b)
		{
			if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b))
			{
				return false;
			}
			return string.Equals(MPUtil.CleanCloneName(a), MPUtil.CleanCloneName(b), StringComparison.OrdinalIgnoreCase);
		}

		public static bool IsBlacklisted(Item item)
		{
			return item != null && (_blacklistedPrefabNames.Contains(MPUtil.CleanCloneName(item.prefabName)) || _blacklistedItemTags.Intersect(item.itemTags).Any());
		}

		public static bool IsBlacklisted(Item_Object itemObj)
		{
			return (Object)(object)itemObj != (Object)null && IsBlacklisted(itemObj.itemData);
		}
	}
}
namespace WKMPMod.Util
{
	public static class Localization
	{
		public struct LocalizedValue
		{
			private readonly object _data;

			public string[] AsArray => _data as string[];

			public string AsString => _data as string;

			public bool IsArray => _data is string[];

			public int Count => (!IsArray) ? 1 : ((string[])_data).Length;

			public LocalizedValue(object data)
			{
				_data = data;
			}

			public string GetValue(int index = 0)
			{
				if (_data is string[] array)
				{
					return array[Math.Clamp(index, 0, array.Length - 1)];
				}
				return _data?.ToString() ?? string.Empty;
			}

			public string GetValue(Random rand)
			{
				if (_data is string[] array)
				{
					return array[rand.Next(array.Length)];
				}
				return _data?.ToString() ?? string.Empty;
			}
		}

		private static Dictionary<string, Dictionary<string, LocalizedValue>> _table;

		private static Dictionary<string, LocalizedValue> _flatCache;

		private const string FILE_PREFIX = "texts";

		private static readonly Random _staticRandom = new Random();

		public static void Load()
		{
			string path = MPMain.path;
			_table = new Dictionary<string, Dictionary<string, LocalizedValue>>();
			string path2 = "texts_en.json";
			string text = Path.Combine(path, path2);
			bool flag = false;
			if (File.Exists(text))
			{
				LoadAndMerge(text);
				flag = true;
			}
			else
			{
				MPMain.LogWarning("[Localization] Base English file not found at: " + text);
			}
			string gameLanguage = GetGameLanguage();
			if (gameLanguage != "en")
			{
				string text2 = "texts_" + gameLanguage.ToLower() + ".json";
				string text3 = Path.Combine(path, text2);
				if (File.Exists(text3))
				{
					LoadAndMerge(text3);
					MPMain.LogInfo("[Localization] Loaded local language file: " + text2 + " and merged over English.");
				}
				else
				{
					MPMain.LogInfo("[Localization] Local language file " + text2 + " not found. Using English fallback.");
				}
			}
			if (_table.Count == 0 && !flag)
			{
				MPMain.LogError("[Localization] CRITICAL: No localization files could be loaded!");
				return;
			}
			BuildFlatCache();
			int num = 0;
			foreach (KeyValuePair<string, Dictionary<string, LocalizedValue>> item in _table)
			{
				num += item.Value.Count;
			}
			MPMain.LogInfo($"[Localization] Successfully loaded {_table.Count} categories with {num} entries");
		}

		private static void LoadAndMerge(string filePath)
		{
			try
			{
				string text = File.ReadAllText(filePath);
				Dictionary<string, Dictionary<string, object>> dictionary = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(text);
				if (dictionary == null)
				{
					return;
				}
				foreach (KeyValuePair<string, Dictionary<string, object>> item in dictionary)
				{
					if (!_table.ContainsKey(item.Key))
					{
						_table[item.Key] = new Dictionary<string, LocalizedValue>();
					}
					foreach (KeyValuePair<string, object> item2 in item.Value)
					{
						object value = item2.Value;
						JArray val = (JArray)((value is JArray) ? value : null);
						if (val != null)
						{
							_table[item.Key][item2.Key] = new LocalizedValue(((IEnumerable<JToken>)val).Select((JToken x) => ((object)x).ToString()).ToArray());
						}
						else
						{
							_table[item.Key][item2.Key] = new LocalizedValue(item2.Value?.ToString());
						}
					}
				}
			}
			catch (Exception ex)
			{
				MPMain.LogError("[Localization] Unable to parse localization file " + Path.GetFileName(filePath) + ": " + ex.Message);
			}
		}

		private static void BuildFlatCache()
		{
			_flatCache = new Dictionary<string, LocalizedValue>(StringComparer.OrdinalIgnoreCase);
			foreach (KeyValuePair<string, Dictionary<string, LocalizedValue>> item in _table)
			{
				foreach (KeyValuePair<string, LocalizedValue> item2 in item.Value)
				{
					string key = item.Key + "." + item2.Key;
					_flatCache[key] = item2.Value;
				}
			}
		}

		public static bool TryGetValueSplit(string category, string key, out LocalizedValue value)
		{
			if (string.IsNullOrEmpty(category))
			{
				MPMain.LogWarning("[MP Localization] Category is null or empty");
				value = new LocalizedValue("[" + category + "." + key + "]");
				return false;
			}
			if (!_table.TryGetValue(category, out Dictionary<string, LocalizedValue> value2))
			{
				MPMain.LogWarning("[MP Localization] Category not found: " + category);
				value = new LocalizedValue("[" + category + "." + key + "]");
				return false;
			}
			if (!value2.TryGetValue(key, out var value3))
			{
				MPMain.LogWarning("[MP Localization] Key '" + key + "' not found in category '" + category + "'");
				value = new LocalizedValue("[" + category + "." + key + "]");
				return false;
			}
			value = value3;
			return true;
		}

		public static string GetSplit(string category, string key, params object[] args)
		{
			if (!TryGetValueSplit(category, key, out var value))
			{
				return value.AsString;
			}
			return SafeFormat(value.AsString, args);
		}

		public static string GetRandomSplit(string category, string key, params object[] args)
		{
			if (!TryGetValueSplit(category, key, out var value))
			{
				return value.AsString;
			}
			return SafeFormat(value.GetValue(_staticRandom), args);
		}

		public static string GetByIndexSplit(string category, string key, int index, params object[] args)
		{
			if (!TryGetValueSplit(category, key, out var value))
			{
				return value.AsString;
			}
			return SafeFormat(value.GetValue(index), args);
		}

		public static int GetCountSplit(string category, string key)
		{
			LocalizedValue value;
			return TryGetValueSplit(category, key, out value) ? value.Count : 0;
		}

		public static string[] GetAllSplit(string category, string key)
		{
			if (!TryGetValueSplit(category, key, out var value))
			{
				return new string[0];
			}
			return value.IsArray ? value.AsArray : new string[1] { value.AsString };
		}

		public static string SafeFormat(string pattern, params object[] args)
		{
			if (string.IsNullOrEmpty(pattern))
			{
				return string.Empty;
			}
			if (args == null || args.Length == 0)
			{
				return pattern;
			}
			try
			{
				MatchCollection matchCollection = Regex.Matches(pattern, "\\{([0-9]+)\\}");
				int num = -1;
				foreach (Match item in matchCollection)
				{
					if (int.TryParse(item.Groups[1].Value, out var result) && result > num)
					{
						num = result;
					}
				}
				if (num == -1)
				{
					return pattern;
				}
				int num2 = num + 1;
				object[] array = new object[num2];
				for (int i = 0; i < num2; i++)
				{
					array[i] = ((i < args.Length && args[i] != null) ? args[i] : "");
				}
				return string.Format(pattern, array);
			}
			catch (Exception ex)
			{
				MPMain.LogError("[Localization] Format error: " + ex.Message + " | Pattern: " + pattern);
				return pattern;
			}
		}

		public static bool TryGetValue(string key, out LocalizedValue value)
		{
			if (!_flatCache.TryGetValue(key, out var value2))
			{
				value = new LocalizedValue("[" + key + "]");
				return false;
			}
			value = value2;
			return true;
		}

		public static string Get(string key, params object[] args)
		{
			if (!TryGetValue(key, out var value))
			{
				return value.AsString;
			}
			return SafeFormat(value.AsString, args);
		}

		public static string GetRandom(string key, params object[] args)
		{
			if (!TryGetValue(key, out var value))
			{
				return value.AsString;
			}
			return SafeFormat(value.GetValue(_staticRandom), args);
		}

		public static string GetByIndex(string key, int index, params object[] args)
		{
			if (!TryGetValue(key, out var value))
			{
				return value.AsString;
			}
			return SafeFormat(value.GetValue(index), args);
		}

		public static int GetCount(string key)
		{
			LocalizedValue value;
			return TryGetValue(key, out value) ? value.Count : 0;
		}

		public static string[] GetAll(string key)
		{
			if (!TryGetValue(key, out var value))
			{
				return new string[0];
			}
			return value.IsArray ? value.AsArray : new string[1] { value.AsString };
		}

		public static bool HasKey(string key)
		{
			return _flatCache.ContainsKey(key);
		}

		public static bool HasKey(string category, string key)
		{
			if (_table.TryGetValue(category, out Dictionary<string, LocalizedValue> value))
			{
				return value.ContainsKey(key);
			}
			return false;
		}

		public static IEnumerable<string> GetAllCategories()
		{
			return _table.Keys;
		}

		public static IEnumerable<string> GetKeysInCategory(string category)
		{
			if (_table.TryGetValue(category, out Dictionary<string, LocalizedValue> value))
			{
				return value.Keys;
			}
			return new List<string>();
		}

		public static string GetGameLanguage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Invalid comparison between Unknown and I4
			SystemLanguage systemLanguage = Application.systemLanguage;
			SystemLanguage val = systemLanguage;
			if ((int)val <= 22)
			{
				if ((int)val <= 14)
				{
					if ((int)val == 6)
					{
						goto IL_0056;
					}
					if ((int)val == 14)
					{
						return "fr";
					}
				}
				else
				{
					if ((int)val == 15)
					{
						return "de";
					}
					if ((int)val == 22)
					{
						return "ja";
					}
				}
			}
			else if ((int)val <= 30)
			{
				if ((int)val == 23)
				{
					return "ko";
				}
				if ((int)val == 30)
				{
					return "ru";
				}
			}
			else
			{
				if ((int)val == 34)
				{
					return "es";
				}
				if ((int)val == 40)
				{
					goto IL_0056;
				}
				if ((int)val == 41)
				{
					return "zh_tw";
				}
			}
			return "en";
			IL_0056:
			return "zh";
		}
	}
	public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
	{
		private static T _instance;

		private static readonly object _lock = new object();

		private static bool _applicationIsQuitting = false;

		public static T Instance
		{
			get
			{
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Expected O, but got Unknown
				if (_applicationIsQuitting)
				{
					return null;
				}
				lock (_lock)
				{
					if ((Object)(object)_instance == (Object)null)
					{
						_instance = Object.FindObjectOfType<T>();
						if ((Object)(object)_instance == (Object)null)
						{
							GameObject val = new GameObject(typeof(T).Name);
							_instance = val.AddComponent<T>();
							Object.DontDestroyOnLoad((Object)(object)val);
						}
					}
					return _instance;
				}
			}
		}

		protected virtual void Awake()
		{
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = (T)this;
				if ((Object)(object)((Component)this).transform.parent == (Object)null)
				{
					Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				}
			}
			else if ((Object)(object)_instance != (Object)(object)this)
			{
				Debug.LogWarning((object)("MonoSingleton<" + typeof(T).Name + ">: Duplicate components were found in the scene and have been automatically destroyed"));
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		protected virtual void OnApplicationQuit()
		{
			_applicationIsQuitting = true;
		}

		protected virtual void OnDestroy()
		{
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}
	}
	public static class MPUtil
	{
		public static readonly Dictionary<string, Color32> PlayerColorPresets = new Dictionary<string, Color32>(StringComparer.OrdinalIgnoreCase)
		{
			{
				"default",
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)
			},
			{
				"white",
				new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)
			},
			{
				"red",
				new Color32(byte.MaxValue, (byte)80, (byte)80, byte.MaxValue)
			},
			{
				"orange",
				new Color32(byte.MaxValue, (byte)165, (byte)0, byte.MaxValue)
			},
			{
				"yellow",
				new Color32(byte.MaxValue, (byte)220, (byte)64, byte.MaxValue)
			},
			{
				"green",
				new Color32((byte)80, (byte)220, (byte)120, byte.MaxValue)
			},
			{
				"cyan",
				new Color32((byte)64, (byte)220, byte.MaxValue, byte.MaxValue)
			},
			{
				"blue",
				new Color32((byte)90, (byte)140, byte.MaxValue, byte.MaxValue)
			},
			{
				"purple",
				new Color32((byte)170, (byte)90, byte.MaxValue, byte.MaxValue)
			},
			{
				"pink",
				new Color32(byte.MaxValue, (byte)110, (byte)180, byte.MaxValue)
			},
			{
				"black",
				new Color32((byte)32, (byte)32, (byte)32, byte.MaxValue)
			}
		};

		public static string CleanCloneName(string prefabKey)
		{
			if (string.IsNullOrEmpty(prefabKey))
			{
				return string.Empty;
			}
			return prefabKey.Replace("(Clone)", string.Empty).Trim();
		}

		public static string SerializePlayerColor(Color32 color)
		{
			//IL_0005: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			return $"{color.r},{color.g},{color.b}";
		}

		public static bool TryParsePlayerColor(string value, out Color32 color)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			color = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string[] array = value.Split(',');
			if (array.Length != 3)
			{
				return false;
			}
			if (!TryParseColorChannel(array[0], out var channel) || !TryParseColorChannel(array[1], out var channel2) || !TryParseColorChannel(array[2], out var channel3))
			{
				return false;
			}
			color = new Color32((byte)channel, (byte)channel2, (byte)channel3, byte.MaxValue);
			return true;
		}

		public static bool TryParseColorChannel(string value, out int channel)
		{
			if (int.TryParse(value.Trim(), out channel))
			{
				return channel >= 0 && channel <= 255;
			}
			return false;
		}
	}
	public static class NestedCommandEngine
	{
		public static readonly FieldRef<CommandConsole, IEnumerable> StatesRef;

		public static readonly FieldRef<object, IDictionary> CommandsRef;

		public static readonly FieldRef<object, Action<CommandAutocomplete>> AutocompleteRef;

		public static readonly FieldRef<CommandAutocomplete, List<string>> AutocompleteArgsRef;

		public static readonly Action<CommandAutocomplete, int> SetAutocompleteActiveArgAction;

		public static readonly FieldRef<object, Action<CommandValidator>> ValidatorRef;

		public static readonly FieldRef<CommandValidator, List<string>> ValidatorArgsRef;

		public static readonly Action<CommandValidator, int> SetValidatorActiveArgAction;

		static NestedCommandEngine()
		{
			try
			{
				Type typeFromHandle = typeof(CommandConsole);
				StatesRef = AccessTools.FieldRefAccess<CommandConsole, IEnumerable>("states");
				Type type = AccessTools.Inner(typeFromHandle, "CommandLineState");
				FieldInfo fieldInfo = AccessTools.Field(type, "commands");
				CommandsRef = AccessTools.FieldRefAccess<object, IDictionary>(fieldInfo);
				Type type2 = AccessTools.Inner(typeFromHandle, "Command");
				FieldInfo fieldInfo2 = AccessTools.Field(type2, "autocomplete");
				AutocompleteRef = AccessTools.FieldRefAccess<object, Action<CommandAutocomplete>>(fieldInfo2);
				FieldInfo fieldInfo3 = AccessTools.Field(type2, "validator");
				ValidatorRef = AccessTools.FieldRefAccess<object, Action<CommandValidator>>(fieldInfo3);
				Type typeFromHandle2 = typeof(CommandAutocomplete);
				AutocompleteArgsRef = AccessTools.FieldRefAccess<CommandAutocomplete, List<string>>("args");
				MethodInfo methodInfo = AccessTools.PropertySetter(typeFromHandle2, "activeArg");
				if (methodInfo != null)
				{
					SetAutocompleteActiveArgAction = AccessTools.MethodDelegate<Action<CommandAutocomplete, int>>(methodInfo, (object)null, true);
				}
				Type typeFromHandle3 = typeof(CommandValidator);
				ValidatorArgsRef = AccessTools.FieldRefAccess<CommandValidator, List<string>>("args");
				MethodInfo methodInfo2 = AccessTools.PropertySetter(typeFromHandle3, "activeArg");
				if (methodInfo2 != null)
				{
					SetValidatorActiveArgAction = AccessTools.MethodDelegate<Action<CommandValidator, int>>(methodInfo2, (object)null, true);
				}
			}
			catch (Exception ex)
			{
				MPMain.LogError(Localization.Get("Patch.HarmonyReflectionInitFailed", ex.Message));
			}
		}

		public static void ForwardAutocomplete(CommandAutocomplete autocomplete, int defaultStartIndex)
		{
			if (StatesRef == null || CommandsRef == null)
			{
				return;
			}
			int num = defaultStartIndex;
			for (int i = defaultStartIndex; i <= autocomplete.activeArg; i++)
			{
				if (autocomplete.ArgumentAt(i) == "::")
				{
					num = i + 1;
				}
			}
			IEnumerable source = StatesRef.Invoke(CommandConsole.instance);
			object obj = source.Cast<object>().First();
			IDictionary dictionary = CommandsRef.Invoke(obj);
			if (autocomplete.activeArg == num)
			{
				List<string> list = new List<string>();
				foreach (object key2 in dictionary.Keys)
				{
					list.Add((string)key2);
				}
				list.Add("::");
				autocomplete.FromArray((IReadOnlyList<string>)list);
			}
			else
			{
				if (autocomplete.activeArg <= num)
				{
					return;
				}
				string key = autocomplete.ArgumentAt(num).ToLower();
				if (dictionary.Contains(key))
				{
					object obj2 = dictionary[key];
					Action<CommandAutocomplete> action = AutocompleteRef.Invoke(obj2);
					if (action != null)
					{
						int activeArg = autocomplete.activeArg;
						List<string> list2 = AutocompleteArgsRef.Invoke(autocomplete);
						SetAutocompleteActiveArgAction(autocomplete, activeArg - num);
						AutocompleteArgsRef.Invoke(autocomplete) = list2.Skip(num).ToList();
						action(autocomplete);
						SetAutocompleteActiveArgAction(autocomplete, activeArg);
						AutocompleteArgsRef.Invoke(autocomplete) = list2;
					}
				}
			}
		}

		public static void ForwardValidator(CommandValidator validator, int defaultStartIndex)
		{
			if (StatesRef == null || CommandsRef == null || ValidatorArgsRef == null)
			{
				return;
			}
			int activeArg = validator.activeArg;
			List<string> list = ValidatorArgsRef.Invoke(validator);
			if (activeArg < defaultStartIndex)
			{
				return;
			}
			int num = defaultStartIndex;
			int num2 = Math.Min(activeArg, list.Count - 1);
			for (int i = defaultStartIndex; i <= num2; i++)
			{
				if (list[i] == "::")
				{
					num = i + 1;
				}
			}
			if (activeArg <= num || num >= list.Count)
			{
				return;
			}
			string key = list[num].ToLower();
			IEnumerable source = StatesRef.Invoke(CommandConsole.instance);
			object obj = source.Cast<object>().First();
			IDictionary dictionary = CommandsRef.Invoke(obj);
			if (dictionary.Contains(key))
			{
				object obj2 = dictionary[key];
				Action<CommandValidator> action = ValidatorRef.Invoke(obj2);
				if (action != null)
				{
					SetValidatorActiveArgAction(validator, activeArg - num);
					ValidatorArgsRef.Invoke(validator) = list.Skip(num).ToList();
					action(validator);
					SetValidatorActiveArgAction(validator, activeArg);
					ValidatorArgsRef.Invoke(validator) = list;
				}
			}
		}
	}
}
namespace WKMPMod.UI
{
	[HarmonyPatch(typeof(UI_GamemodeScreen), "Initialize")]
	public class Patch_UI_GamemodeScreen_Initialize
	{
		private static void Postfix(UI_GamemodeScreen __instance, M_Gamemode mode)
		{
			string id = mode.gamemodePanel.id;
			if (!__instance.activePanels.TryGetValue(id, out var value) || (Object)(object)((Component)value).gameObject.GetComponentInChildren<UI_LobbyCreateButton>(true) != (Object)null)
			{
				return;
			}
			Transform val = ((Component)value).transform.Find("Pages/Gamemode_Info_Screen/Tab Selection Hor/Play");
			TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
			if (((componentInChildren != null) ? ((TMP_Text)componentInChildren).text : null) != "Play")
			{
				val = ((Component)value).transform.Find("Pages/Gamemode_NewGame_Screen/Tab Selection Hor/Play");
			}
			if ((Object)(object)val != (Object)null)
			{
				GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent);
				((Object)val2).name = "Multi Play";
				val2.transform.SetSiblingIndex(val.GetSiblingIndex() + 1);
				UI_LobbyCreateButton uI_LobbyCreateButton = val2.AddComponent<UI_LobbyCreateButton>();
				uI_LobbyCreateButton.gamemodePanel = value;
				TMP_Text componentInChildren2 = val2.GetComponentInChildren<TMP_Text>();
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					componentInChildren2.text = "Multi Play";
				}
				value.noSaveObjects.Add(val2);
				value.hasSaveObjects.Add(val2);
			}
		}
	}
	[HarmonyPatch(typeof(UI_MenuButton), "Initialize")]
	public class Patch_UI_MenuButton_Initialize
	{
		private static bool Prefix(UI_MenuButton __instance, UI_Menu menu)
		{
			if (UI_Manager.IsCloningMultiplayerMenu && ((Object)((Component)__instance).gameObject).name == "Facility Button")
			{
				return false;
			}
			return true;
		}
	}
	public class UI_LoadingDisplay : MonoBehaviour
	{
		private Coroutine? _hideCoroutine;

		private float _hideTime = -1f;

		private float _remainingTime = 0f;

		private void Awake()
		{
			MPEventBusGame.OnShowLoading += HandleLoadingRequest;
			MPEventBusGame.OnHideLoading += HideImmediately;
			((Component)this).gameObject.SetActive(false);
		}

		private void OnDestroy()
		{
			MPEventBusGame.OnShowLoading -= HandleLoadingRequest;
			MPEventBusGame.OnHideLoading -= HideImmediately;
		}

		private void HandleLoadingRequest(float duration)
		{
			if (duration <= 0f)
			{
				ShowPermanent();
			}
			else
			{
				ShowForSeconds(duration);
			}
		}

		public void ShowPermanent()
		{
			if (_hideCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_hideCoroutine);
				_hideCoroutine = null;
			}
			_hideTime = -1f;
			_remainingTime = 0f;
			((Component)this).gameObject.SetActive(true);
		}

		public void ShowForSeconds(float seconds)
		{
			if (!(seconds <= 0f))
			{
				if (_hideCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_hideCoroutine);
					_hideCoroutine = null;
				}
				_hideTime = seconds;
				_remainingTime = seconds;
				((Component)this).gameObject.SetActive(true);
				_hideCoroutine = ((MonoBehaviour)this).StartCoroutine(HideAfterDelay());
			}
		}

		public void ExtendDuration(float seconds)
		{
			if (!(_hideTime < 0f) && _hideCoroutine != null)
			{
				_remainingTime += seconds;
				if (_remainingTime <= 0f)
				{
					HideImmediately();
				}
			}
		}

		public void HideImmediately()
		{
			if (_hideCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_hideCoroutine);
				_hideCoroutine = null;
			}
			_hideTime = -1f;
			_remainingTime = 0f;
			((Component)this).gameObject.SetActive(false);
		}

		private IEnumerator HideAfterDelay()
		{
			while (_remainingTime > 0f)
			{
				yield return null;
				_remainingTime -= Time.deltaTime;
			}
			((Component)this).gameObject.SetActive(false);
			_hideCoroutine = null;
		}

		public float GetRemainingTime()
		{
			return _remainingTime;
		}

		public bool IsShowing()
		{
			return ((Component)this).gameObject.activeSelf;
		}

		public bool IsPermanent()
		{
			return _hideTime < 0f && ((Component)this).gameObject.activeSelf;
		}
	}
	public class UI_LobbyCreateButton : MonoBehaviour
	{
		public Button? button;

		public UI_GamemodeScreen_Panel? gamemodePanel;

		public List<Button> otherButtons = new List<Button>();

		private void Awake()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			Button component = ((Component)this).GetComponent<Button>();
			if ((Object)(object)component != (Object)null)
			{
				component.onClick = new ButtonClickedEvent();
				button = component;
			}
			else
			{
				button = ((Component)this).gameObject.AddComponent<Button>();
			}
			((UnityEvent)button.onClick).AddListener(new UnityAction(CreateLobby));
		}

		private void Start()
		{
			if (!((Object)(object)((Component)this).transform.parent != (Object)null))
			{
				return;
			}
			Button[] componentsInChildren = ((Component)((Component)this).transform.parent).GetComponentsInChildren<Button>();
			foreach (Button val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)(object)button)
				{
					otherButtons.Add(val);
				}
			}
		}

		public async void CreateLobby()
		{
			string name = SteamClient.Name;
			MPMain.LogInfo(Localization.Get("MPCore.CreatingLobby", name));
			Dictionary<string, string> lobbyData = new Dictionary<string, string> { 
			{
				"name",
				name + "'s game"
			} };
			Creating();
			try
			{
				bool success = await MonoSingleton<MPSteamworks>.Instance.CreateRoomAsync(8, lobbyData);
				if (!((Object)(object)this == (Object)null) && !((Object)(object)((Component)this).gameObject == (Object)null))
				{
					if (success)
					{
						CreateSuccess();
					}
					else
					{
						CreateFailed();
					}
				}
			}
			catch (Exception ex)
			{
				Exception ex2 = ex;
				if (!((Object)(object)this == (Object)null))
				{
					CreateFailed();
					MPMain.LogError(Localization.Get("UI_LobbyCreateButton.CreateLobbyFailed", ex2.Message));
				}
			}
		}

		public void Creating()
		{
			MPCore.SetStatus(MPStatus.LobbyConnectionError, MPStatus.JoiningLobby);
			Button? obj = button;
			if (obj != null)
			{
				((Selectable)obj).interactable = false;
			}
			foreach (Button otherButton in otherButtons)
			{
				((Selectable)otherButton).interactable = false;
			}
			MPEventBusGame.NotifyShowLoading(10f);
		}

		public void CreateFailed()
		{
			MPCore.SetStatus(MPStatus.LobbyConnectionError, MPStatus.LobbyConnectionError);
			Button? obj = button;
			if (obj != null)
			{
				((Selectable)obj).interactable = true;
			}
			foreach (Button otherButton in otherButtons)
			{
				((Selectable)otherButton).interactable = true;
			}
			MPEventBusGame.NotifyHideLoading();
		}

		public void CreateSuccess()
		{
			MPCore.SetStatus(MPStatus.LobbyConnectionError, MPStatus.InLobby);
			MPEventBusGame.NotifyHideLoading();
			if ((Object)(object)gamemodePanel == (Object)null)
			{
				MPMain.LogError(Localization.Get("UI_LobbyCreateButton.GameModeDetailPanelNull"));
			}
			else
			{
				gamemodePanel.LoadGamemode();
			}
		}
	}
	public class UI_LobbyJoinButton : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler
	{
		public Lobby lobby;

		public M_Gamemode? gamemode;

		public bool isOfficialGamemodes;

		public MPGameModeManager.GameModeData? gameModeData;

		public UI_LerpOpen? runInProgressDisplay;

		private bool isHovering;

		public TMP_Text? unlockText;

		public float showDelayAnimation;

		public Selectable? button;

		public CanvasGroup? group;

		public Image? unlockIcon;

		public TMP_Text? lobbyName;

		public Image? hostAvatar;

		public TMP_Text? hostName;

		public Button? btnComp;

		public Image? lobbyImage;

		public void Initialize(Lobby lobby)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_009b: Expected O, but got Unknown
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			this.lobby = lobby;
			((UnityEvent)btnComp.onClick).AddListener((UnityAction)async delegate
			{
				Joining();
				try
				{
					if (await MonoSingleton<MPSteamworks>.Instance.JoinRoomAsync(lobby))
					{
						JoinSuccess();
					}
					else
					{
						JoinFailed();
					}
				}
				catch (Exception ex3)
				{
					Exception ex4 = ex3;
					MPMain.LogError(Localization.Get("UI_LobbyJoinButton.JoinLobbyFailed", ex4.Message));
					JoinFailed();
				}
			});
			Image? obj = unlockIcon;
			if (obj != null)
			{
				((Component)obj).gameObject.SetActive(false);
			}
			string data = ((Lobby)(ref lobby)).GetData("gamemode");
			try
			{
				gameModeData = JsonConvert.DeserializeObject<MPGameModeManager.GameModeData>(data);
				MPMain.LogInfo("[MP UI] gameModeName: " + gameModeData?.gameModeName);
			}
			catch (JsonException ex)
			{
				JsonException ex2 = ex;
				MPMain.LogError(Localization.Get("UI_LobbyJoinButton.GamemodeParseError", data, ((Exception)(object)ex2).Message));
			}
			isOfficialGamemodes = MPGameModeManager.TryGetGameMode(gameModeData?.gameModeName ?? "", out M_Gamemode val);
			if (!isOfficialGamemodes)
			{
				Image? obj2 = unlockIcon;
				if (obj2 != null)
				{
					((Component)obj2).gameObject.SetActive(true);
				}
				TMP_Text? obj3 = unlockText;
				if (obj3 != null)
				{
					obj3.text = "Unknown gamemode";
				}
			}
			Version version = new Version("1.7.3");
			if (!Version.TryParse(((Lobby)(ref lobby)).GetData("mod version"), out Version result) || version.Major != result.Major || version.Minor != result.Minor)
			{
				Image? obj4 = unlockIcon;
				if (obj4 != null)
				{
					((Component)obj4).gameObj

WKMultiPlayerMod.Shared.dll

Decompiled 2 days ago
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using WKMPMod.Data;
using WKMPMod.Util;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WKMultiPlayerMod.Shared")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b98d64200e307c3673484e728fc0fe1c77208fc9")]
[assembly: AssemblyProduct("WKMultiPlayerMod.Shared")]
[assembly: AssemblyTitle("WKMultiPlayerMod.Shared")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
[Serializable]
public struct PlayerData : INetworkSerializable
{
	[Serializable]
	public struct HandData : INetworkSerializable
	{
		public byte handType;

		public byte interactState;

		public float PosX;

		public float PosY;

		public float PosZ;

		public string itemName;

		public ulong targetId;

		public float desiredPosX;

		public float desiredPosY;

		public float desiredPosZ;

		public Vector3 Position
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				return new Vector3(PosX, PosY, PosZ);
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				PosX = value.x;
				PosY = value.y;
				PosZ = value.z;
			}
		}

		public Vector3 DesiredPosition
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				return new Vector3(desiredPosX, desiredPosY, desiredPosZ);
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				desiredPosX = value.x;
				desiredPosY = value.y;
				desiredPosZ = value.z;
			}
		}

		public void Serialize(DataWriter writer)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			writer.Put(handType);
			writer.Put(interactState);
			writer.Put(Position);
			switch (interactState)
			{
			case 0:
				writer.Put(itemName);
				break;
			case 2:
				writer.Put(targetId);
				writer.Put(DesiredPosition);
				break;
			case 4:
				writer.Put(targetId);
				break;
			case 1:
			case 3:
				break;
			}
		}

		public void Deserialize(DataReader reader)
		{
			//IL_001b: 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)
			handType = reader.GetByte();
			interactState = reader.GetByte();
			Position = reader.GetVector3();
			switch (interactState)
			{
			case 0:
				itemName = reader.GetString();
				break;
			case 2:
				targetId = reader.GetULong();
				DesiredPosition = reader.GetVector3();
				break;
			case 4:
				targetId = reader.GetULong();
				break;
			case 1:
			case 3:
				break;
			}
		}

		public bool IsBeGrabbing(ulong targetPlayerId)
		{
			return interactState == 2 && targetId == targetPlayerId;
		}

		public bool IsBeHanging(ulong targetPlayerId)
		{
			return interactState == 4 && targetId == targetPlayerId;
		}

		public static bool operator ==(HandData left, HandData right)
		{
			if (left.handType != right.handType || left.interactState != right.interactState)
			{
				return false;
			}
			float num = left.PosX - right.PosX;
			float num2 = left.PosY - right.PosY;
			float num3 = left.PosZ - right.PosZ;
			if (num * num + num2 * num2 + num3 * num3 >= 0.0025f)
			{
				return false;
			}
			switch (left.interactState)
			{
			case 0:
				return left.itemName == right.itemName;
			case 2:
			{
				if (left.targetId != right.targetId)
				{
					return false;
				}
				float num4 = left.desiredPosX - right.desiredPosX;
				float num5 = left.desiredPosY - right.desiredPosY;
				float num6 = left.desiredPosZ - right.desiredPosZ;
				return num4 * num4 + num5 * num5 + num6 * num6 < 0.0025f;
			}
			case 4:
				return left.targetId == right.targetId;
			default:
				return true;
			}
		}

		public static bool operator !=(HandData left, HandData right)
		{
			return !(left == right);
		}
	}

	private const float POSITION_CHANGE_THRESHOLD_SQR = 0.0025f;

	private const float ROTATION_CHANGE_THRESHOLD_DEG = 0.5f;

	public ulong playId;

	public long TimestampTicks;

	public float PosX;

	public float PosY;

	public float PosZ;

	public float RotX;

	public float RotY;

	public float RotZ;

	public float RotW;

	public HandData LeftHand;

	public HandData RightHand;

	public bool IsTeleport;

	public Vector3 Position
	{
		get
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(PosX, PosY, PosZ);
		}
		set
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			PosX = value.x;
			PosY = value.y;
			PosZ = value.z;
		}
	}

	public Quaternion Rotation
	{
		get
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			return new Quaternion(RotX, RotY, RotZ, RotW);
		}
		set
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			RotX = value.x;
			RotY = value.y;
			RotZ = value.z;
			RotW = value.w;
		}
	}

	public void Serialize(DataWriter writer)
	{
		//IL_001b: 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)
		writer.Put(playId).Put(TimestampTicks);
		writer.Put(Position).Put(Rotation);
		writer.PutIn(in LeftHand).PutIn(in RightHand);
		writer.Put(IsTeleport);
	}

	public void Deserialize(DataReader reader)
	{
		//IL_001b: 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)
		playId = reader.GetULong();
		TimestampTicks = reader.GetLong();
		Position = reader.GetVector3();
		Rotation = reader.GetQuaternion();
		reader.GetRef(ref LeftHand);
		reader.GetRef(ref RightHand);
		IsTeleport = reader.GetBool();
	}

	public bool UpdateIfChanged(in PlayerData newData, bool forceUpdate = false)
	{
		//IL_0058: 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)
		if (forceUpdate)
		{
			this = newData;
			return true;
		}
		float num = PosX - newData.PosX;
		float num2 = PosY - newData.PosY;
		float num3 = PosZ - newData.PosZ;
		if (num * num + num2 * num2 + num3 * num3 >= 0.0025f || !IsRotationSimilar(Rotation, newData.Rotation, 0.5f) || LeftHand != newData.LeftHand || RightHand != newData.RightHand)
		{
			this = newData;
			return true;
		}
		return false;
	}

	private static bool IsRotationSimilar(Quaternion a, Quaternion b, float thresholdDegrees)
	{
		//IL_0014: 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)
		float num = Mathf.Cos(thresholdDegrees * (MathF.PI / 180f) * 0.5f);
		float num2 = Mathf.Abs(Quaternion.Dot(a, b));
		return num2 > num;
	}
}
namespace WKMPMod.Util
{
	public static class DictionaryExtensions
	{
		public static List<ulong> FindByKeySuffix<T>(this Dictionary<ulong, T> dictionary, ulong suffix)
		{
			List<ulong> list = new List<ulong>();
			if (dictionary == null || dictionary.Count == 0)
			{
				return list;
			}
			ulong num = CalculateDivisor(suffix);
			foreach (KeyValuePair<ulong, T> item in dictionary)
			{
				if (item.Key % num == suffix)
				{
					list.Add(item.Key);
				}
			}
			return list;
		}

		private static ulong CalculateDivisor(ulong suffix)
		{
			if (suffix == 0)
			{
				return 10uL;
			}
			ulong num;
			for (num = 1uL; num <= suffix; num *= 10)
			{
			}
			return num;
		}

		public static Dictionary<K, byte> SetDifference<K>(Dictionary<K, byte> minuend, Dictionary<K, byte> subtrahend)
		{
			Dictionary<K, byte> dictionary = new Dictionary<K, byte>();
			foreach (var (key, b2) in minuend)
			{
				if (subtrahend.TryGetValue(key, out var value))
				{
					if (b2 > value)
					{
						dictionary[key] = (byte)(b2 - value);
					}
				}
				else
				{
					dictionary[key] = b2;
				}
			}
			return dictionary;
		}
	}
	public class TickTimer
	{
		private float _interval;

		private float _lastTickTime;

		public float Progress => Mathf.Clamp01((Time.time - _lastTickTime) / _interval);

		public float TimeRemaining => Mathf.Max(0f, _interval - (Time.time - _lastTickTime));

		public bool IsTickReached => Time.time - _lastTickTime >= _interval;

		public TickTimer(float tick)
		{
			_interval = tick;
			_lastTickTime = 0f - _interval;
		}

		public TickTimer(int hz)
		{
			_interval = 1f / (float)hz;
			_lastTickTime = 0f - _interval;
		}

		public void SetInterval(float tick)
		{
			_interval = tick;
		}

		public void SetFrequency(float hz)
		{
			_interval = 1f / hz;
		}

		public void Reset()
		{
			_lastTickTime = Time.time;
		}

		public bool TryTick()
		{
			if (Time.time - _lastTickTime >= _interval)
			{
				_lastTickTime = Time.time;
				return true;
			}
			return false;
		}

		public void ForceTick()
		{
			_lastTickTime = Time.time;
		}
	}
}
namespace WKMPMod.MK_Component
{
	public class MK_CL_Handhold : MonoBehaviour
	{
		public UnityEvent activeEvent = new UnityEvent();

		public UnityEvent stopEvent = new UnityEvent();

		public Renderer handholdRenderer;
	}
	public class MK_ObjectTagger : MonoBehaviour
	{
		public List<string> tags = new List<string>();
	}
	public class MK_RemoteEntity : MonoBehaviour
	{
		public ulong playerId;
	}
	public class MK_RemoteHand : MonoBehaviour
	{
		[Header("左右手")]
		public byte hand;

		[Header("距离设置")]
		[Tooltip("当当前位置与目标位置超过此距离时直接瞬移")]
		public float teleportThreshold = 50f;

		[Tooltip("平滑移动的最大距离限制")]
		public float fastSmoothDistance = 10f;

		[Header("拉拽参数")]
		public float basePullStrength = 0.2f;

		public void Teleport(Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.position = position;
		}
	}
}
namespace WKMPMod.Data
{
	public class DataReader
	{
		private ReadOnlyMemory<byte> _data;

		private int _position;

		public int AvailableBytes => _data.Length - _position;

		public void SetSource(ArraySegment<byte> source)
		{
			_data = source;
			_position = 0;
		}

		public void SetSource(byte[] source)
		{
			_data = source;
			_position = 0;
		}

		public void SetSource(byte[] source, int offset, int length)
		{
			_data = new ReadOnlyMemory<byte>(source, offset, length);
			_position = 0;
		}

		public bool GetBool()
		{
			bool result = _data.Span[_position] != 0;
			_position++;
			return result;
		}

		public byte GetByte()
		{
			byte result = _data.Span[_position];
			_position++;
			return result;
		}

		public short GetShort()
		{
			short result = BinaryPrimitives.ReadInt16LittleEndian(_data.Span.Slice(_position));
			_position += 2;
			return result;
		}

		public ushort GetUShort()
		{
			ushort result = BinaryPrimitives.ReadUInt16LittleEndian(_data.Span.Slice(_position));
			_position += 2;
			return result;
		}

		public int GetInt()
		{
			int result = BinaryPrimitives.ReadInt32LittleEndian(_data.Span.Slice(_position));
			_position += 4;
			return result;
		}

		public uint GetUInt()
		{
			uint result = BinaryPrimitives.ReadUInt32LittleEndian(_data.Span.Slice(_position));
			_position += 4;
			return result;
		}

		public long GetLong()
		{
			long result = BinaryPrimitives.ReadInt64LittleEndian(_data.Span.Slice(_position));
			_position += 8;
			return result;
		}

		public ulong GetULong()
		{
			ulong result = BinaryPrimitives.ReadUInt64LittleEndian(_data.Span.Slice(_position));
			_position += 8;
			return result;
		}

		public float GetFloat()
		{
			int value = BinaryPrimitives.ReadInt32LittleEndian(_data.Span.Slice(_position));
			_position += 4;
			return BitConverter.Int32BitsToSingle(value);
		}

		public double GetDouble()
		{
			long value = BinaryPrimitives.ReadInt64LittleEndian(_data.Span.Slice(_position));
			_position += 8;
			return BitConverter.Int64BitsToDouble(value);
		}

		public byte? GetNullableByte()
		{
			if (!GetBool())
			{
				return null;
			}
			return GetByte();
		}

		public int? GetNullableInt()
		{
			if (!GetBool())
			{
				return null;
			}
			return GetInt();
		}

		public float? GetNullableFloat()
		{
			if (!GetBool())
			{
				return null;
			}
			return GetFloat();
		}

		public Vector3 GetVector3()
		{
			//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_0069: Unknown result type (might be due to invalid IL or missing references)
			ReadOnlySpan<byte> source = _data.Span.Slice(_position);
			float num = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source));
			float num2 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(4)));
			float num3 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(8)));
			_position += 12;
			return new Vector3(num, num2, num3);
		}

		public Quaternion GetQuaternion()
		{
			//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)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			ReadOnlySpan<byte> source = _data.Span.Slice(_position);
			float num = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source));
			float num2 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(4)));
			float num3 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(8)));
			float num4 = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(source.Slice(12)));
			_position += 16;
			return new Quaternion(num, num2, num3, num4);
		}

		public string GetString()
		{
			int num = GetInt();
			if (num <= 0)
			{
				return string.Empty;
			}
			if (num > AvailableBytes)
			{
				throw new Exception("String length out of range");
			}
			string result = Encoding.UTF8.GetString(_data.Span.Slice(_position, num));
			_position += num;
			return result;
		}

		public ReadOnlySpan<byte> GetBytes()
		{
			int num = GetInt();
			ReadOnlySpan<byte> result = _data.Span.Slice(_position, num);
			_position += num;
			return result;
		}

		public ReadOnlyMemory<byte> GetMemory()
		{
			int num = GetInt();
			ReadOnlyMemory<byte> result = _data.Slice(_position, num);
			_position += num;
			return result;
		}

		public Dictionary<string, byte> GetStringByteDict()
		{
			int num = GetInt();
			Dictionary<string, byte> dictionary = new Dictionary<string, byte>();
			for (int i = 0; i < num; i++)
			{
				string key = GetString();
				byte value = GetByte();
				dictionary[key] = value;
			}
			return dictionary;
		}

		public List<string> GetStringList()
		{
			List<string> list = new List<string>();
			int num = GetInt();
			for (int i = 0; i < num; i++)
			{
				list.Add(GetString());
			}
			return list;
		}

		public Dictionary<string, string> GetStringStringDict()
		{
			int num = GetInt();
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			for (int i = 0; i < num; i++)
			{
				string key = GetString();
				string value = GetString();
				dictionary[key] = value;
			}
			return dictionary;
		}

		public T Get<T>() where T : INetworkSerializable, new()
		{
			T result = new T();
			result.Deserialize(this);
			return result;
		}

		public void GetOut<T>(out T value) where T : struct, INetworkSerializable
		{
			value = default(T);
			value.Deserialize(this);
		}

		public void GetRef<T>(ref T value) where T : struct, INetworkSerializable
		{
			value.Deserialize(this);
		}

		public List<T> GetList<T>() where T : INetworkSerializable, new()
		{
			int num = GetInt();
			if (num <= 0)
			{
				return new List<T>(0);
			}
			List<T> list = new List<T>(num);
			for (int i = 0; i < num; i++)
			{
				T item = new T();
				item.Deserialize(this);
				list.Add(item);
			}
			return list;
		}

		public void GetList<T>(List<T> existingList) where T : INetworkSerializable, new()
		{
			int num = GetInt();
			existingList.Clear();
			for (int i = 0; i < num; i++)
			{
				T item = new T();
				item.Deserialize(this);
				existingList.Add(item);
			}
		}
	}
	public class DataWriter : IDisposable
	{
		private byte[] _buffer;

		private int _position;

		private readonly ArrayPool<byte> _pool;

		public ArraySegment<byte> Data => new ArraySegment<byte>(_buffer, 0, _position);

		public DataWriter(int initialCapacity = 1024)
		{
			_pool = ArrayPool<byte>.Shared;
			_buffer = _pool.Rent(initialCapacity);
			_position = 0;
		}

		public byte[] ToArray()
		{
			byte[] array = new byte[_position];
			Array.Copy(_buffer, 0, array, 0, _position);
			return array;
		}

		public void CopyDataTo(byte[] target, int targetOffset = 0)
		{
			if (target.Length - targetOffset < _position)
			{
				throw new ArgumentException("Target buffer is too small");
			}
			Array.Copy(_buffer, 0, target, targetOffset, _position);
		}

		public void Reset()
		{
			_position = 0;
		}

		public DataWriter Put(bool value)
		{
			EnsureCapacity(1);
			_buffer[_position] = (byte)(value ? 1u : 0u);
			_position++;
			return this;
		}

		public DataWriter Put(byte value)
		{
			EnsureCapacity(1);
			_buffer[_position] = value;
			_position++;
			return this;
		}

		public DataWriter Put(short value)
		{
			EnsureCapacity(2);
			BinaryPrimitives.WriteInt16LittleEndian(_buffer.AsSpan(_position), value);
			_position += 2;
			return this;
		}

		public DataWriter Put(ushort value)
		{
			EnsureCapacity(2);
			BinaryPrimitives.WriteUInt16LittleEndian(_buffer.AsSpan(_position), value);
			_position += 2;
			return this;
		}

		public DataWriter Put(int value)
		{
			EnsureCapacity(4);
			BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(_position), value);
			_position += 4;
			return this;
		}

		public DataWriter Put(uint value)
		{
			EnsureCapacity(4);
			BinaryPrimitives.WriteUInt32LittleEndian(_buffer.AsSpan(_position), value);
			_position += 4;
			return this;
		}

		public DataWriter Put(long value)
		{
			EnsureCapacity(8);
			BinaryPrimitives.WriteInt64LittleEndian(_buffer.AsSpan(_position), value);
			_position += 8;
			return this;
		}

		public DataWriter Put(ulong value)
		{
			EnsureCapacity(8);
			BinaryPrimitives.WriteUInt64LittleEndian(_buffer.AsSpan(_position), value);
			_position += 8;
			return this;
		}

		public DataWriter Put(float value)
		{
			EnsureCapacity(4);
			int value2 = BitConverter.SingleToInt32Bits(value);
			BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(_position), value2);
			_position += 4;
			return this;
		}

		public DataWriter Put(double value)
		{
			EnsureCapacity(8);
			long value2 = BitConverter.DoubleToInt64Bits(value);
			BinaryPrimitives.WriteInt64LittleEndian(_buffer.AsSpan(_position), value2);
			_position += 8;
			return this;
		}

		public DataWriter Put(byte? value)
		{
			if (!value.HasValue)
			{
				Put(value: false);
			}
			else
			{
				Put(value: true);
				Put(value.Value);
			}
			return this;
		}

		public DataWriter Put(int? value)
		{
			if (!value.HasValue)
			{
				Put(value: false);
			}
			else
			{
				Put(value: true);
				Put(value.Value);
			}
			return this;
		}

		public DataWriter Put(float? value)
		{
			if (!value.HasValue)
			{
				Put(value: false);
			}
			else
			{
				Put(value: true);
				Put(value.Value);
			}
			return this;
		}

		public DataWriter Put(byte[] value)
		{
			if (value == null)
			{
				return Put(0);
			}
			return Put(value, 0, value.Length);
		}

		public DataWriter Put(byte[] value, int offset, int length)
		{
			if (value == null)
			{
				EnsureCapacity(4);
				BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(_position), 0);
				_position += 4;
				return this;
			}
			Put(length);
			EnsureCapacity(length);
			Array.Copy(value, offset, _buffer, _position, length);
			_position += length;
			return this;
		}

		public DataWriter Put(ReadOnlySpan<byte> value)
		{
			Put(value.Length);
			EnsureCapacity(value.Length);
			value.CopyTo(_buffer.AsSpan(_position));
			_position += value.Length;
			return this;
		}

		public DataWriter Put(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				Put(0);
				return this;
			}
			int maxByteCount = Encoding.UTF8.GetMaxByteCount(value.Length);
			EnsureCapacity(maxByteCount + 4);
			int position = _position;
			_position += 4;
			int bytes = Encoding.UTF8.GetBytes(value, 0, value.Length, _buffer, _position);
			BinaryPrimitives.WriteInt32LittleEndian(_buffer.AsSpan(position), bytes);
			_position += bytes;
			return this;
		}

		public DataWriter Put(Vector3 value)
		{
			//IL_001d: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			EnsureCapacity(12);
			Span<byte> destination = _buffer.AsSpan(_position);
			BinaryPrimitives.WriteInt32LittleEndian(destination, BitConverter.SingleToInt32Bits(value.x));
			BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(4), BitConverter.SingleToInt32Bits(value.y));
			BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(8), BitConverter.SingleToInt32Bits(value.z));
			_position += 12;
			return this;
		}

		public DataWriter Put(Quaternion value)
		{
			//IL_001d: 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_004f: 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)
			EnsureCapacity(16);
			Span<byte> destination = _buffer.AsSpan(_position);
			BinaryPrimitives.WriteInt32LittleEndian(destination, BitConverter.SingleToInt32Bits(value.x));
			BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(4), BitConverter.SingleToInt32Bits(value.y));
			BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(8), BitConverter.SingleToInt32Bits(value.z));
			BinaryPrimitives.WriteInt32LittleEndian(destination.Slice(12), BitConverter.SingleToInt32Bits(value.w));
			_position += 16;
			return this;
		}

		public DataWriter Put(Dictionary<string, byte> dict)
		{
			if (dict == null)
			{
				Put(0);
				return this;
			}
			Put(dict.Count);
			foreach (KeyValuePair<string, byte> item in dict)
			{
				Put(item.Key).Put(item.Value);
			}
			return this;
		}

		public DataWriter Put(IReadOnlyList<string> strings)
		{
			if (strings == null)
			{
				Put(0);
				return this;
			}
			Put(strings.Count);
			foreach (string @string in strings)
			{
				Put(@string);
			}
			return this;
		}

		public DataWriter Put(Dictionary<string, string> dict)
		{
			if (dict == null)
			{
				Put(0);
				return this;
			}
			Put(dict.Count);
			foreach (KeyValuePair<string, string> item in dict)
			{
				Put(item.Key).Put(item.Value);
			}
			return this;
		}

		public DataWriter Put<T>(T obj) where T : INetworkSerializable
		{
			obj.Serialize(this);
			return this;
		}

		public DataWriter PutIn<T>(in T obj) where T : struct, INetworkSerializable
		{
			obj.Serialize(this);
			return this;
		}

		public DataWriter Put<T>(IReadOnlyList<T> list) where T : INetworkSerializable
		{
			if (list == null || list.Count == 0)
			{
				Put(0);
				return this;
			}
			Put(list.Count);
			foreach (T item in list)
			{
				item.Serialize(this);
			}
			return this;
		}

		public void EnsureCapacity(int additional)
		{
			if (_position + additional > _buffer.Length)
			{
				byte[] array = _pool.Rent((_position + additional) * 2);
				Array.Copy(_buffer, 0, array, 0, _position);
				_pool.Return(_buffer);
				_buffer = array;
			}
		}

		public void Dispose()
		{
			if (_buffer != null)
			{
				_pool.Return(_buffer);
				_buffer = null;
				_position = 0;
			}
		}
	}
	public interface INetworkSerializable
	{
		void Serialize(DataWriter writer);

		void Deserialize(DataReader reader);
	}
}
namespace WKMPMod.Component
{
	public class LookAt : MonoBehaviour
	{
		private Camera? mainCamera;

		[Header("锁定大小")]
		public bool maintainScreenSize = true;

		[Header("初始缩放比例")]
		public float baseScale = 0.1f;

		[Header("用户设置缩放比例")]
		public float userScale = 1f;

		private void LateUpdate()
		{
			//IL_0044: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mainCamera == (Object)null)
			{
				mainCamera = Camera.main;
				if ((Object)(object)mainCamera == (Object)null)
				{
					return;
				}
			}
			((Component)this).transform.rotation = ((Component)mainCamera).transform.rotation;
			if (maintainScreenSize)
			{
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)mainCamera).transform.position);
				float num2 = ((!(num < 10f)) ? num : (0.8f * num + 2f));
				float num3 = num2 * baseScale * userScale;
				((Component)this).transform.localScale = new Vector3(num3, num3, num3);
			}
		}
	}
	public class RemotePlayer : MonoBehaviour
	{
		public ulong playerId;

		[Header("距离设置")]
		[Tooltip("当当前位置与目标位置超过此距离时直接瞬移")]
		public float teleportThreshold = 50f;

		[Tooltip("平滑移动的最大距离限制")]
		public float maxSmoothDistance = 10f;

		private bool _isTeleporting = false;

		private Vector3 _targetPosition;

		private Vector3 _velocity = Vector3.zero;

		private void LateUpdate()
		{
			//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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_00fa: 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)
			if (_isTeleporting)
			{
				return;
			}
			float num = Vector3.Distance(((Component)this).transform.position, _targetPosition);
			if (num > teleportThreshold)
			{
				Teleport(_targetPosition);
			}
			else if (((Component)this).transform.position != _targetPosition)
			{
				float num2 = CalculateSmoothTime(num);
				((Component)this).transform.position = Vector3.SmoothDamp(((Component)this).transform.position, _targetPosition, ref _velocity, num2, float.MaxValue, Time.deltaTime);
				if (((Vector3)(ref _velocity)).magnitude < 0.5f && num > 0.05f)
				{
					Vector3 val = _targetPosition - ((Component)this).transform.position;
					Vector3 normalized = ((Vector3)(ref val)).normalized;
					_velocity = normalized * 0.5f;
				}
			}
		}

		private float CalculateSmoothTime(float distance)
		{
			if (distance > maxSmoothDistance)
			{
				return Mathf.Clamp(Mathf.Log(distance) * 0.1f, 0.05f, 0.3f);
			}
			return Mathf.Clamp(distance / 10f, 0.05f, 0.1f);
		}

		public void UpdateFromPlayerData(Vector3 position, Quaternion rotation)
		{
			//IL_0009: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			_isTeleporting = false;
			_targetPosition = position;
			((Component)this).transform.rotation = rotation;
		}

		public void UpdateFromPlayerData(ref PlayerData playerData)
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			_isTeleporting = false;
			_targetPosition = playerData.Position;
			((Component)this).transform.rotation = playerData.Rotation;
		}

		public void Teleport(Vector3 position, Quaternion? rotation = null)
		{
			//IL_000e: 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_0017: 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_0022: 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)
			_isTeleporting = true;
			((Component)this).transform.position = position;
			_targetPosition = position;
			_velocity = Vector3.zero;
			if (rotation.HasValue)
			{
				((Component)this).transform.rotation = rotation.Value;
			}
			((MonoBehaviour)this).StartCoroutine(ResetTeleportFlag());
		}

		private IEnumerator ResetTeleportFlag()
		{
			yield return null;
			_isTeleporting = false;
		}
	}
	public class RemoteTag : MonoBehaviour
	{
		private Transform? _cameraTransform;

		private TextMeshPro? _textMeshPro;

		private float _lastUpdateDistance;

		private TickTimer updateTick = new TickTimer(1);

		[Header("Settings")]
		public const float MIN_DISTANCE_LABEL = 10f;

		public const float DISTANCE_CHANGE_THRESHOLD = 1f;

		public const float MESSAGE_TIMEOUT = 15f;

		[Header("Id")]
		public ulong PlayerId;

		[Header("名字")]
		public string PlayerName = "";

		[Header("Message")]
		public string _message = "";

		private Coroutine? _messageTimeoutCoroutine;

		public string Message
		{
			get
			{
				return _message;
			}
			set
			{
				string text = ((value.Length <= 15) ? value : value.Substring(0, 15));
				if (!(_message == text))
				{
					_message = text;
					if (_messageTimeoutCoroutine != null)
					{
						((MonoBehaviour)this).StopCoroutine(_messageTimeoutCoroutine);
					}
					_messageTimeoutCoroutine = ((MonoBehaviour)this).StartCoroutine(MessageTimeoutRoutine());
					RefreshName();
				}
			}
		}

		private void Awake()
		{
			_textMeshPro = ((Component)this).GetComponent<TextMeshPro>();
			if ((Object)(object)Camera.main != (Object)null)
			{
				_cameraTransform = ((Component)Camera.main).transform;
			}
		}

		private void OnDestroy()
		{
			if (_messageTimeoutCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_messageTimeoutCoroutine);
			}
		}

		private void Update()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (!updateTick.TryTick())
			{
				return;
			}
			if ((Object)(object)_cameraTransform == (Object)null)
			{
				if (!((Object)(object)Camera.main != (Object)null))
				{
					Debug.LogError((object)"[MP RemoteTag]No main camera found");
					return;
				}
				_cameraTransform = ((Component)Camera.main).transform;
			}
			float num = Vector3.Distance(((Component)this).transform.position, _cameraTransform.position);
			if (Mathf.Abs(num - _lastUpdateDistance) >= 1f)
			{
				RefreshName(num);
			}
		}

		public void Initialize(ulong playerId, string playerName)
		{
			PlayerId = playerId;
			PlayerName = playerName;
		}

		public void RefreshName()
		{
			//IL_001a: 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)
			if (!((Object)(object)_cameraTransform == (Object)null))
			{
				RefreshName(Vector3.Distance(((Component)this).transform.position, _cameraTransform.position));
			}
		}

		private void RefreshName(float currentDistance)
		{
			_lastUpdateDistance = currentDistance;
			if (!((Object)(object)_textMeshPro == (Object)null))
			{
				string text = currentDistance.ToString("F0");
				if (currentDistance < 10f)
				{
					((TMP_Text)_textMeshPro).text = (string.IsNullOrEmpty(_message) ? PlayerName : (PlayerName + "\n" + _message));
					return;
				}
				((TMP_Text)_textMeshPro).text = (string.IsNullOrEmpty(_message) ? (PlayerName + " (" + text + "m)") : (PlayerName + " (" + text + "m)\n" + _message));
			}
		}

		private IEnumerator MessageTimeoutRoutine()
		{
			yield return (object)new WaitForSeconds(15f);
			_message = "";
			RefreshName();
			_messageTimeoutCoroutine = null;
		}
	}
	public class SimpleArmIK : MonoBehaviour
	{
		[Header("目标设置")]
		public Transform? target;

		public float originalLength = 1f;

		[Header("限制")]
		public float minScale = 0.1f;

		public float maxScale = 10f;

		private void Start()
		{
			//IL_0029: 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)
			if (originalLength <= 0f && (Object)(object)target != (Object)null)
			{
				originalLength = Vector3.Distance(((Component)this).transform.position, target.position);
			}
		}

		private void LateUpdate()
		{
			//IL_001c: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0055: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null))
			{
				Vector3 val = target.position - ((Component)this).transform.position;
				float magnitude = ((Vector3)(ref val)).magnitude;
				if (!(magnitude < 0.0001f))
				{
					((Component)this).transform.rotation = Quaternion.FromToRotation(Vector3.up, val);
					float num = magnitude / originalLength;
					num = Mathf.Clamp(num, minScale, maxScale);
					((Component)this).transform.localScale = new Vector3(1f, num, 1f);
				}
			}
		}
	}
}