Decompiled source of QuickPocket v1.0.12

BepInEx/plugins/HiarlyScripter-QuickPocket/HiarlyScripter-QuickPocket.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("HiarlyScripter-QuickPocket")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.12.0")]
[assembly: AssemblyInformationalVersion("1.0.12")]
[assembly: AssemblyProduct("HiarlyScripter-QuickPocket")]
[assembly: AssemblyTitle("HiarlyScripter-QuickPocket")]
[assembly: AssemblyVersion("1.0.12.0")]
namespace QuickPocket;

[BepInPlugin("com.hiarlyscripter.quickpocket", "QuickPocket", "1.0.12")]
[BepInProcess("REPO.exe")]
public class QuickPocketPlugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	internal static QuickPocketPlugin Instance;

	internal static ConfigEntry<KeyboardShortcut> PocketKey;

	internal static ConfigEntry<int> MaxPocketSlots;

	internal static ConfigEntry<float> MaxItemBoundsSize;

	internal static ConfigEntry<float> PocketCooldown;

	internal static ConfigEntry<bool> AllowWeapons;

	internal static ConfigEntry<bool> AllowMelee;

	internal static ConfigEntry<bool> AllowOrbs;

	internal static ConfigEntry<bool> AllowDrones;

	internal static ConfigEntry<bool> AllowEnemyItems;

	internal static ConfigEntry<bool> AllowDuplicates;

	internal static ConfigEntry<bool> UseHostPocketLimit;

	internal static ConfigEntry<int> HostMaxOverride;

	internal static ConfigEntry<bool> SyncPocketState;

	internal static ConfigEntry<bool> ShowPocketHUD;

	internal static ConfigEntry<bool> HudAlwaysVisible;

	internal static ConfigEntry<float> HudFadeSeconds;

	internal static ConfigEntry<bool> AutoDropIfHandsFull;

	internal static ConfigEntry<bool> DropOnDeath;

	internal static ConfigEntry<bool> DropOnLevelChange;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		BindConfigs();
		RepoCompat.Initialize();
		if (!RepoCompat.IsCompatible)
		{
			Log.LogError((object)"[QuickPocket] Inicializacao cancelada por incompatibilidade. Ver logs acima.");
			return;
		}
		_harmony = new Harmony("com.hiarlyscripter.quickpocket");
		_harmony.PatchAll();
		Log.LogInfo((object)"[QuickPocket] v1.0.12 (update jogo 06/11) inicializado. Aguardando jogador...");
	}

	private void BindConfigs()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Expected O, but got Unknown
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Expected O, but got Unknown
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Expected O, but got Unknown
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		PocketKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "PocketKey", new KeyboardShortcut((KeyCode)104, Array.Empty<KeyCode>()), "Key to store/retrieve items from the pocket. Edit via .cfg (not shown in REPOConfig).");
		MaxPocketSlots = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxPocketSlots", 4, new ConfigDescription("Maximum number of pocket slots (personal). Host limit may override this.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>()));
		MaxItemBoundsSize = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxItemBoundsSize", 1.25f, new ConfigDescription("Max item size in meters (largest dimension). Items above this are rejected.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
		PocketCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PocketCooldown", 0.5f, new ConfigDescription("Cooldown in seconds between pocket actions.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
		AllowWeapons = ((BaseUnityPlugin)this).Config.Bind<bool>("Restrictions", "AllowWeapons", false, "Allow storing firearms, explosives and launchers in the pocket.");
		AllowMelee = ((BaseUnityPlugin)this).Config.Bind<bool>("Restrictions", "AllowMelee", false, "Allow storing melee weapons in the pocket.");
		AllowOrbs = ((BaseUnityPlugin)this).Config.Bind<bool>("Restrictions", "AllowOrbs", true, "Allow storing orbs (health/utility pickups) in the pocket.");
		AllowDrones = ((BaseUnityPlugin)this).Config.Bind<bool>("Restrictions", "AllowDrones", false, "Allow storing drones in the pocket.");
		AllowEnemyItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Restrictions", "AllowEnemyItems", false, "Allow storing items physically attached to enemy entities.");
		AllowDuplicates = ((BaseUnityPlugin)this).Config.Bind<bool>("Restrictions", "AllowDuplicates", true, "Allow storing multiple items of the same type simultaneously.");
		UseHostPocketLimit = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "UseHostLimit", true, "If true, clients use the host's HostMaxOverride slot limit.");
		HostMaxOverride = ((BaseUnityPlugin)this).Config.Bind<int>("Multiplayer", "HostMaxOverride", 4, new ConfigDescription("Slot limit published by the host for the whole room. Requires UseHostLimit=true.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>()));
		SyncPocketState = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "SyncPocketState", true, "If true, other players see items disappear/reappear when pocketed/retrieved.");
		ShowPocketHUD = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "ShowPocketHUD", true, "Show the QuickPocket HUD on screen.");
		HudAlwaysVisible = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "HudAlwaysVisible", false, "If true, HUD stays visible while items are in the pocket. If false, it fades.");
		HudFadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "HudFadeSeconds", 4f, new ConfigDescription("Seconds the HUD remains visible after a pocket/unpocket action.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
		AutoDropIfHandsFull = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "AutoDropIfHandsFull", true, "If hands are occupied when retrieving, drop the item beside the player instead.");
		DropOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "DropOnDeath", true, "Drop all pocketed items at the death position when the player dies.");
		DropOnLevelChange = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "DropOnLevelChange", true, "Drop all pocketed items when the level changes.");
		ManualLogSource log = Log;
		string[] obj = new string[10] { "[QuickPocket] Configs carregadas: Key=", null, null, null, null, null, null, null, null, null };
		KeyboardShortcut value = PocketKey.Value;
		obj[1] = ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString();
		obj[2] = " Slots=";
		obj[3] = MaxPocketSlots.Value.ToString();
		obj[4] = " HostMax=";
		obj[5] = HostMaxOverride.Value.ToString();
		obj[6] = " UseHostLimit=";
		obj[7] = UseHostPocketLimit.Value.ToString();
		obj[8] = " Sync=";
		obj[9] = SyncPocketState.Value.ToString();
		log.LogDebug((object)string.Concat(obj));
	}
}
internal class PendingRequest
{
	internal int Nonce;

	internal int ViewID;

	internal float Timestamp;

	internal int Actor;

	internal string Type;

	internal string State;

	internal PendingRequest(int nonce, int viewID, float timestamp, int actor, string type, string state)
	{
		Nonce = nonce;
		ViewID = viewID;
		Timestamp = timestamp;
		Actor = actor;
		Type = type;
		State = state;
	}
}
public class PocketManager : MonoBehaviour, IInRoomCallbacks, IMatchmakingCallbacks, IOnEventCallback
{
	private const string PROP_HOST_MAX_SLOTS = "QP_HostMaxSlots";

	private const string PROP_USE_HOST_LIMIT = "QP_UseHostLimit";

	private const float LATE_JOIN_TIMEOUT = 10f;

	private readonly List<int> _localPocket = new List<int>();

	private readonly Dictionary<int, ComponentSnapshot> _snapshots = new Dictionary<int, ComponentSnapshot>();

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

	private readonly Dictionary<int, List<int>> _remoteHides = new Dictionary<int, List<int>>();

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

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

	private bool _isPocketing;

	private float _cooldownTimer;

	private float _lastEnforce;

	private bool _hasLocalPocketManager;

	private bool _hudGameplayReady;

	private bool _hudSuppressedForTransition = true;

	private bool _cachedRunIsLevel;

	private static MethodInfo _runIsLevelMethod = null;

	private static bool _runIsLevelChecked = false;

	private static FieldInfo _loadingUIAnimCompleted = null;

	private const int _HUD_STABLE_FRAMES = 5;

	private int _runIsLevelTrueStreak;

	private const float HUD_UNLOCK_MIN_WAIT = 2f;

	private bool _cachedIsLoading = true;

	private static int _hudGeneration = 0;

	private int _managerGeneration = -1;

	private bool _loadingAnimDone;

	private bool _loadingUIWasSeen;

	private float _loadingAnimDoneTime;

	private static int _layerRoomVolume = -1;

	private static bool _layersInitialized = false;

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

	private const byte EV_REQUEST_POCKET = 71;

	private const byte EV_ACK_POCKET = 72;

	private const byte EV_DENY_POCKET = 73;

	private const byte EV_REQUEST_DROP = 74;

	private const byte EV_ACK_DROP = 75;

	private const byte EV_DENY_DROP = 76;

	private const float MP_REQUEST_TIMEOUT = 5f;

	private readonly Dictionary<int, List<(int vid, ComponentSnapshot snap)>> _hostedPockets = new Dictionary<int, List<(int, ComponentSnapshot)>>();

	private readonly Dictionary<int, ComponentSnapshot> _remoteSnapshots = new Dictionary<int, ComponentSnapshot>();

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

	private readonly Dictionary<int, PendingRequest> _pendingPocketAcks = new Dictionary<int, PendingRequest>();

	private readonly Dictionary<int, PendingRequest> _pendingDropAcks = new Dictionary<int, PendingRequest>();

	private int _nonce;

	private static readonly float[] DROP_ANGLES_NORMAL = new float[12]
	{
		0f, 30f, -30f, 60f, -60f, 90f, -90f, 120f, -120f, 150f,
		-150f, 180f
	};

	private static readonly float[] DROP_ANGLES_SIDE = new float[12]
	{
		90f, -90f, 60f, -60f, 120f, -120f, 0f, 30f, -30f, 150f,
		-150f, 180f
	};

	private int _dropCandidateIndex;

	private float _dropCandidateResetT;

	private const float DROP_RESET_SECS = 6f;

	private static readonly Collider[] _overlapBuffer = (Collider[])(object)new Collider[32];

	private const float DROP_SEARCH_RADIUS = 1.2f;

	private const float DROP_SPHERE_R = 0.28f;

	private const float DROP_MAX_FLOOR_DELTA = 1.5f;

	private const float DROP_ITEM_HEIGHT = 0.2f;

	private const float DROP_CEILING_MIN = 0.5f;

	private const float DROP_GROUND_CAST = 4f;

	private string _hudActionMessage = "";

	private float _hudActionMessageTime = -999f;

	private bool _limitSynced;

	private int _cachedEffectiveLimit = -1;

	private bool _lateJoinProcessed;

	private const float DROP_CONFIRM_MAX_DIST_CHOSEN = 1f;

	private const float DROP_CONFIRM_MAX_DIST_PLAYER = 2.5f;

	private const float DROP_CONFIRM_MAX_DELTA_Y = 1f;

	internal static PocketManager Instance { get; private set; }

	private string PropKeyForActor(int actor)
	{
		return "QP_" + actor;
	}

	private void SetHudMessage(string msg)
	{
		_hudActionMessage = msg;
		_hudActionMessageTime = Time.time;
	}

	private static string GetRejectHudMessage(string reason)
	{
		switch (reason)
		{
		case "PlayerObjectBlocked":
			return "Nao cabe gente viva no bolso.";
		case "PlayerBodyBlocked":
			return "Esse ai ainda tem CPF.";
		case "PlayerDeathHeadBlocked":
			return "Cabeca de jogador fica fora do bolso.";
		case "PhaseBridgeBlocked":
		case "WorldPropBlocked":
			return "Isso e parte do nivel, nao um item.";
		case "UpgradeBlocked":
			return "Upgrades ficam no lugar.";
		case "ScreamDollBlocked":
		case "SpecialItemBlocked":
			return "Esse item nao pode ser guardado.";
		case "DeployableBlocked":
			return "Deployables ficam no lugar.";
		case "MeleeBlocked":
		case "WeaponBlocked":
			return "Armas nao cabem no bolso.";
		case "DroneBlocked":
			return "Drones nao cabem no bolso.";
		case "EnemyBlocked":
			return "Isso e um inimigo, nao um item.";
		case "EnemyParentBlocked":
			return "Esse item esta preso a um inimigo.";
		case "OrbBlocked":
			return "Orbs bloqueados nas configs.";
		default:
			return "";
		}
	}

	private static string CleanItemName(string raw)
	{
		if (raw == null)
		{
			return "";
		}
		return raw.Replace("(Clone)", "").TrimEnd(Array.Empty<char>());
	}

	private static bool HasPendingRequest(Dictionary<int, PendingRequest> requests, int viewID)
	{
		foreach (KeyValuePair<int, PendingRequest> request in requests)
		{
			if (request.Value != null && request.Value.ViewID == viewID)
			{
				return true;
			}
		}
		return false;
	}

	private void TrackPending(Dictionary<int, PendingRequest> requests, int nonce, int viewID, string type)
	{
		int actor = ((SemiFunc.IsMultiplayer() && PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
		requests[nonce] = new PendingRequest(nonce, viewID, Time.time, actor, type, "Waiting");
	}

	private void ClearPendingRequests(string reason, bool hudReset)
	{
		int num = ((SemiFunc.IsMultiplayer() && PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
		int num2 = _pendingPocketAcks.Count + _pendingDropAcks.Count;
		_pendingPocketAcks.Clear();
		_pendingDropAcks.Clear();
		if (hudReset && _hudActionMessage == "Aguarde...")
		{
			SetHudMessage("");
		}
		if (num2 > 0)
		{
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] cleanup actor=" + num + " reason=" + reason + " restored=0 pendingCleared=" + num2 + " hudReset=" + hudReset));
		}
	}

	private ComponentSnapshot SaveLocalSnapshotFor(GameObject go, int viewID, int actorNumber)
	{
		if ((Object)(object)go == (Object)null)
		{
			return null;
		}
		PhysGrabObject component = go.GetComponent<PhysGrabObject>();
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		ComponentSnapshot componentSnapshot = PocketOperations.SaveSnapshot(component, viewID, actorNumber);
		if (!PocketOperations.ValidateSnapshot(componentSnapshot))
		{
			return null;
		}
		return componentSnapshot;
	}

	private ComponentSnapshot FindHostedSnapshot(int actorNumber, int viewID)
	{
		if (!_hostedPockets.TryGetValue(actorNumber, out List<(int, ComponentSnapshot)> value))
		{
			return null;
		}
		for (int i = 0; i < value.Count; i++)
		{
			if (value[i].Item1 == viewID)
			{
				return value[i].Item2;
			}
		}
		return null;
	}

	private void HideRemoteItem(int viewID, GameObject go, int actorNumber, HideMode mode, string reason)
	{
		if (!((Object)(object)go == (Object)null))
		{
			ComponentSnapshot componentSnapshot = SaveLocalSnapshotFor(go, viewID, actorNumber);
			if (componentSnapshot != null)
			{
				_remoteSnapshots[viewID] = componentSnapshot;
			}
			PocketOperations.HidePocketedItemState(go, viewID, actorNumber, mode, reason, componentSnapshot);
		}
	}

	private void RestoreRemoteItem(int viewID, GameObject go, int actorNumber, RestoreMode mode, Vector3? finalPos, string reason)
	{
		if (!((Object)(object)go == (Object)null))
		{
			_remoteSnapshots.TryGetValue(viewID, out var value);
			PocketOperations.RestorePocketedItemState(go, viewID, actorNumber, mode, finalPos, reason, value);
			_remoteSnapshots.Remove(viewID);
		}
	}

	private void SendHostedDropRequest(int viewID, Vector3 clientPos, string reason, bool trackPending)
	{
		//IL_0015: 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_002b: Expected O, but got Unknown
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Expected O, but got Unknown
		//IL_003c: 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)
		//IL_0052: Expected O, but got Unknown
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Expected O, but got Unknown
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		//IL_008b: Expected O, but got Unknown
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		int num = ++_nonce;
		Hashtable val = new Hashtable();
		((Dictionary<object, object>)val).Add((object)"vid", (object)viewID);
		((Dictionary<object, object>)val).Add((object)"nonce", (object)num);
		((Dictionary<object, object>)val).Add((object)"cpx", (object)clientPos.x);
		((Dictionary<object, object>)val).Add((object)"cpy", (object)clientPos.y);
		((Dictionary<object, object>)val).Add((object)"cpz", (object)clientPos.z);
		((Dictionary<object, object>)val).Add((object)"reason", (object)reason);
		Hashtable val2 = val;
		RaiseEventOptions val3 = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)2
		};
		PhotonNetwork.RaiseEvent((byte)74, (object)val2, val3, SendOptions.SendReliable);
		if (trackPending)
		{
			TrackPending(_pendingDropAcks, num, viewID, "Drop");
		}
		int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
		QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] request drop actor=" + actorNumber + " viewID=" + viewID + " nonce=" + num + " clientPos=" + ((Vector3)(ref clientPos)).ToString("F2") + " reason=" + reason));
	}

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			QuickPocketPlugin.Log.LogDebug((object)("[QP:Manager] stale suppressed id=" + ((Object)Instance).GetInstanceID() + " -> new id=" + ((Object)this).GetInstanceID() + " gen=" + _hudGeneration));
		}
		else
		{
			QuickPocketPlugin.Log.LogDebug((object)("[QP:Manager] instance set id=" + ((Object)this).GetInstanceID() + " gen=" + _hudGeneration));
		}
		Instance = this;
		_managerGeneration = _hudGeneration;
		_hasLocalPocketManager = true;
		_hudSuppressedForTransition = true;
		_runIsLevelTrueStreak = 0;
		_loadingAnimDone = false;
		_loadingUIWasSeen = false;
		_loadingAnimDoneTime = 0f;
	}

	private void OnDestroy()
	{
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}

	private void OnEnable()
	{
		PhotonNetwork.AddCallbackTarget((object)this);
		SceneManager.sceneLoaded += OnSceneLoaded;
		QuickPocketPlugin.Log.LogDebug((object)"[QuickPocket] PocketManager: callbacks Photon + SceneManager registrados.");
	}

	private void OnDisable()
	{
		PhotonNetwork.RemoveCallbackTarget((object)this);
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		if (!((Object)(object)this != (Object)(object)Instance) && _managerGeneration == _hudGeneration && (!_hudSuppressedForTransition || _hudGameplayReady))
		{
			_hudGeneration++;
			_hudGameplayReady = false;
			_hudSuppressedForTransition = true;
			_runIsLevelTrueStreak = 0;
			_loadingAnimDone = false;
			_loadingUIWasSeen = false;
			_managerGeneration = _hudGeneration;
			QuickPocketPlugin.Log.LogDebug((object)("[QP:HUDState] gen=" + _hudGeneration + " allowed=false reason=SceneLoaded scene=" + ((Scene)(ref scene)).name));
		}
	}

	private void Start()
	{
		if (PhotonNetwork.InRoom)
		{
			ProcessLateJoin();
		}
	}

	private void Update()
	{
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)this != (Object)(object)Instance || _managerGeneration != _hudGeneration)
		{
			return;
		}
		if (_cooldownTimer > 0f)
		{
			_cooldownTimer -= Time.deltaTime;
		}
		if (Time.time - _lastEnforce > 1f)
		{
			EnforcePocketState();
			_lastEnforce = Time.time;
		}
		if (_pendingLateJoin.Count > 0)
		{
			ProcessPendingLateJoin();
		}
		if (_pendingPocketAcks.Count > 0 || _pendingDropAcks.Count > 0)
		{
			CheckRequestTimeouts();
		}
		_cachedIsLoading = IsLoadingActive();
		if (_cachedIsLoading)
		{
			_loadingUIWasSeen = true;
		}
		_cachedRunIsLevel = TrySemiRunIsLevel();
		if (!_loadingAnimDone && _loadingUIWasSeen && !_cachedIsLoading && _cachedRunIsLevel)
		{
			_loadingAnimDone = true;
			_loadingAnimDoneTime = Time.time;
			QuickPocketPlugin.Log.LogDebug((object)("[QP:HUDState] gen=" + _hudGeneration + " loadingAnimDone=true reason=Fallback"));
		}
		if (_hudSuppressedForTransition)
		{
			bool flag = Time.time - _loadingAnimDoneTime >= 2f;
			if (_cachedRunIsLevel && _loadingAnimDone && flag)
			{
				_runIsLevelTrueStreak++;
				if (_runIsLevelTrueStreak >= 5)
				{
					_hudSuppressedForTransition = false;
					_hudGameplayReady = true;
					QuickPocketPlugin.Log.LogDebug((object)("[QP:HUDState] gen=" + _hudGeneration + " allowed=true reason=FreshAvatarGameplayConfirmed streak=" + _runIsLevelTrueStreak));
				}
			}
			else
			{
				_runIsLevelTrueStreak = 0;
			}
		}
		else if (!_cachedRunIsLevel)
		{
			_hudGameplayReady = false;
			_hudSuppressedForTransition = true;
			_runIsLevelTrueStreak = 0;
			_loadingAnimDone = false;
			QuickPocketPlugin.Log.LogDebug((object)("[QP:HUDState] gen=" + _hudGeneration + " allowed=false reason=RunIsLevelFalse"));
		}
		KeyboardShortcut value = QuickPocketPlugin.PocketKey.Value;
		if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
		{
			HandlePocketKey();
		}
	}

	private GameObject FindPocketedObject(int key)
	{
		if (SemiFunc.IsMultiplayer())
		{
			PhotonView val = PhotonView.Find(key);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).gameObject;
		}
		GameObject value;
		bool num = _singleplayerObjects.TryGetValue(key, out value);
		bool flag = (Object)(object)value == (Object)null;
		if (!num || flag)
		{
			return null;
		}
		return value;
	}

	private void HandlePocketKey()
	{
		try
		{
			if (_isPocketing)
			{
				return;
			}
			if (_cooldownTimer > 0f)
			{
				SetHudMessage("Aguarde...");
			}
			else if (SemiFunc.PhysGrabberLocalIsGrabbing())
			{
				TryPocket();
			}
			else if (_localPocket.Count > 0)
			{
				if (Input.GetMouseButton(0))
				{
					SetHudMessage("Solte o botao de grab antes de retirar.");
				}
				else
				{
					TryUnpocket();
				}
			}
		}
		catch (Exception ex)
		{
			QuickPocketPlugin.Log.LogDebug((object)("[QP:HandlePocketKey] excecao: " + ex.GetType().Name + " — " + ex.Message));
		}
	}

	private void TryPocket()
	{
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0393: Invalid comparison between Unknown and I4
		//IL_059a: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a0: Invalid comparison between Unknown and I4
		//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_04be: Expected O, but got Unknown
		//IL_04be: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d0: Expected O, but got Unknown
		//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e1: Expected O, but got Unknown
		//IL_04e3: Expected O, but got Unknown
		//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f1: Expected O, but got Unknown
		//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
		_isPocketing = true;
		try
		{
			int effectiveLimit = GetEffectiveLimit();
			if (effectiveLimit < 0)
			{
				SetHudMessage("Sincronizando limite...");
				QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Sincronizando limite — tente novamente.");
				return;
			}
			if (_localPocket.Count >= effectiveLimit)
			{
				SetHudMessage("Bolso cheio! (" + _localPocket.Count + "/" + effectiveLimit + ")");
				QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Bolso cheio (" + _localPocket.Count + "/" + effectiveLimit + ")."));
				return;
			}
			PhysGrabObject val;
			try
			{
				val = SemiFunc.PhysGrabberLocalGetGrabbedPhysGrabObject();
			}
			catch (Exception ex)
			{
				QuickPocketPlugin.Log.LogDebug((object)("[QP:TryPocket] fallback=ExceptionCaught source=PhysGrabberLocal exception=" + ex.GetType().Name));
				return;
			}
			if ((Object)(object)val == (Object)null)
			{
				QuickPocketPlugin.Log.LogDebug((object)"[QuickPocket] PhysGrabObject nulo.");
				return;
			}
			PhysGrabObject val2 = ResolveRootPgo(val);
			if ((Object)(object)val2 == (Object)null)
			{
				QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Rejected: Item=" + ((Object)((Component)val).gameObject).name + " Reason=InvalidHeldObject"));
				return;
			}
			QuickPocketPlugin.Log.LogDebug((object)("[QP:TryPocket] heldRaw=" + ((Object)((Component)val).gameObject).name + " resolvedPgo=" + ((Object)((Component)val2).gameObject).name + " actor=" + (SemiFunc.IsMultiplayer() ? PhotonNetwork.LocalPlayer.ActorNumber.ToString() : "SP") + " isMaster=" + SemiFunc.IsMasterClientOrSingleplayer()));
			if (RepoCompat.GetIsEnemy(val2) && (Object)(object)((Component)val2).gameObject.GetComponent<ItemAttributes>() == (Object)null)
			{
				QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Rejected: Item=" + ((Object)((Component)val2).gameObject).name + " Reason=InvalidHeldObject"));
				return;
			}
			EligibilityInfo eligibilityInfo = EligibilityChecker.Evaluate(val2);
			if (!eligibilityInfo.Eligible)
			{
				if (eligibilityInfo.RejectReason == "TooLarge" && eligibilityInfo.RejectedMaxDim > 0f)
				{
					float value = QuickPocketPlugin.MaxItemBoundsSize.Value;
					float ratio = ((value > 0f) ? (eligibilityInfo.RejectedMaxDim / value) : 2f);
					SetHudMessage(FunnyMessages.GetTooLargeMessage(ratio));
					return;
				}
				string rejectHudMessage = GetRejectHudMessage(eligibilityInfo.RejectReason);
				if (!string.IsNullOrEmpty(rejectHudMessage))
				{
					SetHudMessage(rejectHudMessage);
				}
				return;
			}
			if (!QuickPocketPlugin.AllowDuplicates.Value)
			{
				foreach (int item in _localPocket)
				{
					if (_snapshots.TryGetValue(item, out var value2) && value2.ItemName == eligibilityInfo.ItemName)
					{
						SetHudMessage("Ja tem um desse no bolso.");
						QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Rejected: Item=" + eligibilityInfo.ItemName + " Reason=DuplicateBlocked"));
						return;
					}
				}
			}
			PhotonView component = ((Component)val2).gameObject.GetComponent<PhotonView>();
			if (SemiFunc.IsMultiplayer())
			{
				if ((Object)(object)component == (Object)null)
				{
					QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Item sem PhotonView em multiplayer — nao pode ser sincronizado.");
					return;
				}
				string text = (component.IsMine ? "IsMine" : (((int)component.OwnershipTransfer == 1) ? "Takeover" : "DirectFixed"));
				QuickPocketPlugin.Log.LogDebug((object)("[QP:TryPocket] pv=" + component.ViewID + " isMine=" + component.IsMine + " owner=" + component.OwnerActorNr + " ownershipTransfer=" + ((object)Unsafe.As<OwnershipOption, OwnershipOption>(ref component.OwnershipTransfer)/*cast due to .constrained prefix*/).ToString() + " policy=" + text));
				if (!SemiFunc.IsMasterClientOrSingleplayer())
				{
					int viewID = component.ViewID;
					if (_localPocket.Contains(viewID))
					{
						QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Item ja esta no bolso.");
						return;
					}
					if (HasPendingRequest(_pendingPocketAcks, viewID))
					{
						SetHudMessage("Aguarde...");
						return;
					}
					int num = ++_nonce;
					Hashtable val3 = new Hashtable();
					((Dictionary<object, object>)val3).Add((object)"vid", (object)viewID);
					((Dictionary<object, object>)val3).Add((object)"nonce", (object)num);
					((Dictionary<object, object>)val3).Add((object)"item", (object)eligibilityInfo.ItemName);
					Hashtable val4 = val3;
					RaiseEventOptions val5 = new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)2
					};
					PhotonNetwork.RaiseEvent((byte)71, (object)val4, val5, SendOptions.SendReliable);
					TrackPending(_pendingPocketAcks, num, viewID, "Pocket");
					SetHudMessage("Aguarde...");
					int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
					QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] request pocket actor=" + actorNumber + " viewID=" + viewID + " item=" + eligibilityInfo.ItemName + " nonce=" + num));
					return;
				}
				if (!component.IsMine && (int)component.OwnershipTransfer == 1)
				{
					component.RequestOwnership();
					QuickPocketPlugin.Log.LogDebug((object)("[QuickPocket] RequestOwnership (Takeover) para " + eligibilityInfo.ItemName));
				}
			}
			int num2 = (SemiFunc.IsMultiplayer() ? component.ViewID : ((Object)((Component)val2).gameObject).GetInstanceID());
			if (!SemiFunc.IsMultiplayer())
			{
				_singleplayerObjects[num2] = ((Component)val2).gameObject;
			}
			if (_localPocket.Contains(num2))
			{
				QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Item ja esta no bolso.");
				return;
			}
			int num3 = (((Object)(object)component != (Object)null) ? component.OwnerActorNr : 0);
			ComponentSnapshot componentSnapshot = PocketOperations.SaveSnapshot(val2, num2, num3);
			if (!PocketOperations.ValidateSnapshot(componentSnapshot))
			{
				QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Pocket cancelado: snapshot invalido para " + eligibilityInfo.ItemName));
				return;
			}
			if (!PocketOperations.HidePocketedItemState(((Component)val2).gameObject, num2, num3, HideMode.Local, "TryPocket", componentSnapshot))
			{
				QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Pocket cancelado: HideState falhou para " + eligibilityInfo.ItemName));
				return;
			}
			_localPocket.Add(num2);
			_snapshots[num2] = componentSnapshot;
			SetHudMessage("Guardado: " + CleanItemName(eligibilityInfo.ItemName) + " (" + _localPocket.Count + "/" + effectiveLimit + ")");
			PublishPocketedItems();
			QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Pocketado: " + eligibilityInfo.ItemName + " (" + _localPocket.Count + "/" + effectiveLimit + ")"));
		}
		finally
		{
			_isPocketing = false;
			_cooldownTimer = QuickPocketPlugin.PocketCooldown.Value;
		}
	}

	private bool TryFindSafeDropPosition(PlayerAvatar player, bool preferSide, out Vector3 position, out string failReason)
	{
		//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_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: 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)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: 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_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		//IL_039d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_041a: Unknown result type (might be due to invalid IL or missing references)
		//IL_041c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0459: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: Unknown result type (might be due to invalid IL or missing references)
		//IL_0467: Unknown result type (might be due to invalid IL or missing references)
		//IL_046e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0473: Unknown result type (might be due to invalid IL or missing references)
		//IL_0475: Unknown result type (might be due to invalid IL or missing references)
		//IL_047a: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_048e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0497: Unknown result type (might be due to invalid IL or missing references)
		position = Vector3.zero;
		failReason = null;
		if (Time.time - _dropCandidateResetT > 6f)
		{
			_dropCandidateIndex = 0;
		}
		int num = -5;
		Vector3 position2 = ((Component)player).transform.position;
		PhysGrabObject val = SemiFunc.PhysGrabberLocalGetGrabbedPhysGrabObject();
		GameObject grabbedGo = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
		Camera main = Camera.main;
		Vector3 val3;
		if ((Object)(object)main != (Object)null)
		{
			Vector3 forward = ((Component)main).transform.forward;
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(forward.x, 0f, forward.z);
			val3 = ((((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val2)).normalized : ((Component)player).transform.forward);
		}
		else
		{
			val3 = ((Component)player).transform.forward;
		}
		float num2 = (((Object)(object)main != (Object)null) ? (((Component)main).transform.position.y - 0.6f) : (position2.y + 0.7f));
		Vector3 val4 = default(Vector3);
		((Vector3)(ref val4))..ctor(position2.x, num2, position2.z);
		RaycastHit val5 = default(RaycastHit);
		float num3 = (Physics.Raycast(position2 + Vector3.up * 0.1f, Vector3.down, ref val5, 3f, num, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val5)).point.y : position2.y);
		float[] array = (preferSide ? DROP_ANGLES_SIDE : DROP_ANGLES_NORMAL);
		int num4 = array.Length;
		Vector3 val7 = default(Vector3);
		RaycastHit val8 = default(RaycastHit);
		Vector3 val10 = default(Vector3);
		RaycastHit val12 = default(RaycastHit);
		for (int i = 0; i < num4; i++)
		{
			int num5 = (_dropCandidateIndex + i) % num4;
			float num6 = array[num5];
			Vector3 val6 = Quaternion.AngleAxis(num6, Vector3.up) * val3;
			((Vector3)(ref val7))..ctor(position2.x + val6.x * 1.2f, position2.y + 0.8f, position2.z + val6.z * 1.2f);
			if (!Physics.Raycast(val7, Vector3.down, ref val8, 4f, num, (QueryTriggerInteraction)1))
			{
				QuickPocketPlugin.Log.LogDebug((object)("[QP:SafeDrop] ang=" + num6.ToString("F0") + " gate=GATE1 result=FAIL reason=NoFloor origin=" + ((Vector3)(ref val7)).ToString("F2") + " castDist=" + 4f.ToString("F1")));
				continue;
			}
			ManualLogSource log = QuickPocketPlugin.Log;
			string[] obj = new string[8]
			{
				"[QP:SafeDrop] ang=",
				num6.ToString("F0"),
				" gate=GATE1 result=OK floor=",
				null,
				null,
				null,
				null,
				null
			};
			Vector3 val9 = ((RaycastHit)(ref val8)).point;
			obj[3] = ((Vector3)(ref val9)).ToString("F2");
			obj[4] = " normal.y=";
			val9 = ((RaycastHit)(ref val8)).normal;
			obj[5] = val9.y.ToString("F2");
			obj[6] = " layer=";
			obj[7] = LayerMask.LayerToName(((Component)((RaycastHit)(ref val8)).collider).gameObject.layer);
			log.LogDebug((object)string.Concat(obj));
			if (((RaycastHit)(ref val8)).normal.y < 0.7f)
			{
				ManualLogSource log2 = QuickPocketPlugin.Log;
				string text = num6.ToString("F0");
				val9 = ((RaycastHit)(ref val8)).normal;
				log2.LogDebug((object)("[QP:SafeDrop] ang=" + text + " gate=GATE1b result=FAIL reason=TooSteep normal.y=" + val9.y.ToString("F2")));
				continue;
			}
			float num7 = Mathf.Abs(((RaycastHit)(ref val8)).point.y - num3);
			if (num7 > 1.5f)
			{
				QuickPocketPlugin.Log.LogDebug((object)("[QP:SafeDrop] ang=" + num6.ToString("F0") + " gate=GATE2 result=FAIL reason=FloorDelta=" + num7.ToString("F2")));
				continue;
			}
			((Vector3)(ref val10))..ctor(val7.x, ((RaycastHit)(ref val8)).point.y + 0.2f, val7.z);
			if (!IsDropSphereClear(new Vector3(val10.x, ((RaycastHit)(ref val8)).point.y + 0.28f + 0.02f, val10.z), 0.28f, num, player, grabbedGo, out var blockerName))
			{
				QuickPocketPlugin.Log.LogDebug((object)("[QP:SafeDrop] ang=" + num6.ToString("F0") + " gate=GATE4 result=FAIL reason=SphereFull blocker=" + (blockerName ?? "?")));
				continue;
			}
			if (Physics.Raycast(val10, Vector3.up, 0.5f, num, (QueryTriggerInteraction)1))
			{
				QuickPocketPlugin.Log.LogDebug((object)("[QP:SafeDrop] ang=" + num6.ToString("F0") + " gate=GATE5 result=FAIL reason=LowCeiling"));
				continue;
			}
			Vector3 val11 = new Vector3(val10.x, val4.y, val10.z) - val4;
			float magnitude = ((Vector3)(ref val11)).magnitude;
			if (magnitude > 0.05f && Physics.SphereCast(val4, 0.28f, ((Vector3)(ref val11)).normalized, ref val12, magnitude, num, (QueryTriggerInteraction)1))
			{
				QuickPocketPlugin.Log.LogDebug((object)("[QP:SafeDrop] ang=" + num6.ToString("F0") + " gate=GATE6 result=FAIL reason=WallBlocked"));
				continue;
			}
			_dropCandidateIndex = (num5 + 1) % num4;
			_dropCandidateResetT = Time.time;
			position = val10;
			QuickPocketPlugin.Log.LogInfo((object)("[QP:SafeDrop] ang=" + num6.ToString("F0") + " result=OK pos=" + ((Vector3)(ref val10)).ToString("F2")));
			return true;
		}
		failReason = "Sem espaco para soltar aqui.";
		QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Drop bloqueado: sem candidato valido.");
		return false;
	}

	private static bool IsDropSphereClear(Vector3 center, float radius, int mask, PlayerAvatar player, GameObject grabbedGo, out string blockerName)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		blockerName = null;
		EnsureLayersInitialized();
		int num = Physics.OverlapSphereNonAlloc(center, radius, _overlapBuffer, mask, (QueryTriggerInteraction)1);
		for (int i = 0; i < num; i++)
		{
			Collider val = _overlapBuffer[i];
			if (!((Object)(object)val == (Object)null))
			{
				GameObject gameObject = ((Component)val).gameObject;
				int layer = gameObject.layer;
				if ((_layerRoomVolume < 0 || layer != _layerRoomVolume) && (!((Object)(object)player != (Object)null) || !((Component)val).transform.IsChildOf(((Component)player).transform)) && (!((Object)(object)grabbedGo != (Object)null) || !((Component)val).transform.IsChildOf(grabbedGo.transform)))
				{
					blockerName = ((Object)gameObject).name + " layer=" + LayerMask.LayerToName(layer) + " path=" + BuildShortPath(((Component)val).transform);
					return false;
				}
			}
		}
		return true;
	}

	private static string BuildShortPath(Transform t)
	{
		if ((Object)(object)t == (Object)null)
		{
			return "?";
		}
		Transform root = t.root;
		if (!((Object)(object)root != (Object)(object)t))
		{
			return ((Object)t).name;
		}
		return ((Object)root).name + "/" + ((Object)t).name;
	}

	private static void EnsureLayersInitialized()
	{
		if (!_layersInitialized)
		{
			_layersInitialized = true;
			_layerRoomVolume = LayerMask.NameToLayer("RoomVolume");
			QuickPocketPlugin.Log.LogDebug((object)("[QuickPocket] Layers inicializadas: RoomVolume=" + _layerRoomVolume));
		}
	}

	private IEnumerator ConfirmAndFinalizeDrop(GameObject go, ComponentSnapshot snap, int viewID, Vector3 chosenDropPos, Vector3 playerPosAtDrop, Vector3 originalPos)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: 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_0033: 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)
		yield return (object)new WaitForSeconds(0.3f);
		_pendingRestore.Remove(viewID);
		if (!((Object)(object)go != (Object)null))
		{
			_localPocket.Remove(viewID);
			_snapshots.Remove(viewID);
			_singleplayerObjects.Remove(viewID);
			SetHudMessage("Drop falhou. Tente em outro lugar.");
			QuickPocketPlugin.Log.LogWarning((object)("[QuickPocket] Drop FALHOU: " + snap.ItemName + " destruido apos 0.3s."));
			PublishPocketedItems();
			yield break;
		}
		Vector3 position = go.transform.position;
		float num = Vector3.Distance(position, chosenDropPos);
		float num2 = Vector3.Distance(position, playerPosAtDrop);
		float num3 = Mathf.Abs(position.y - chosenDropPos.y);
		bool flag = num <= 1f && num2 <= 2.5f && num3 <= 1f;
		QuickPocketPlugin.Log.LogInfo((object)("[QP:DropConfirm] item=" + snap.ItemName + " viewID=" + viewID + " original=" + ((Vector3)(ref originalPos)).ToString("F2") + " chosen=" + ((Vector3)(ref chosenDropPos)).ToString("F2") + " final=" + ((Vector3)(ref position)).ToString("F2") + " distChosen=" + num.ToString("F2") + " distPlayer=" + num2.ToString("F2") + " deltaY=" + num3.ToString("F2") + " result=" + (flag ? "OK" : "FAIL")));
		if (!flag)
		{
			PocketOperations.ApplyHide(go, snap);
			SetHudMessage("Drop falhou. Tente em outro lugar.");
			QuickPocketPlugin.Log.LogWarning((object)("[QuickPocket] Drop FALHOU: " + snap.ItemName + " moveu " + num.ToString("F2") + "m — re-pocketado."));
			yield break;
		}
		Rigidbody component = go.GetComponent<Rigidbody>();
		Collider componentInChildren = go.GetComponentInChildren<Collider>();
		QuickPocketPlugin.Log.LogDebug((object)("[QP:DropConfirm] item=" + snap.ItemName + " result=OK layer=" + LayerMask.LayerToName(go.layer) + " colliderEnabled=" + (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.enabled.ToString() : "none") + " detectCollisions=" + (((Object)(object)component != (Object)null) ? component.detectCollisions.ToString() : "none") + " isKinematic=" + (((Object)(object)component != (Object)null) ? component.isKinematic.ToString() : "none") + " useGravity=" + (((Object)(object)component != (Object)null) ? component.useGravity.ToString() : "none")));
		_localPocket.Remove(viewID);
		_snapshots.Remove(viewID);
		_singleplayerObjects.Remove(viewID);
		int count = _localPocket.Count;
		int effectiveLimit = GetEffectiveLimit();
		SetHudMessage("Retirado: " + CleanItemName(snap.ItemName) + " (" + count + "/" + effectiveLimit + ")");
		QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Drop confirmado: " + snap.ItemName + " (" + count + "/" + effectiveLimit + ")"));
		PublishPocketedItems();
	}

	private static PhysGrabObject ResolveRootPgo(PhysGrabObject pgo)
	{
		if ((Object)(object)pgo == (Object)null)
		{
			return null;
		}
		PhysGrabObject result = pgo;
		Transform parent = ((Component)pgo).transform.parent;
		while ((Object)(object)parent != (Object)null)
		{
			PhysGrabObject component = ((Component)parent).GetComponent<PhysGrabObject>();
			if ((Object)(object)component != (Object)null)
			{
				result = component;
			}
			parent = parent.parent;
		}
		return result;
	}

	private void TryUnpocket()
	{
		//IL_0097: 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_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Expected O, but got Unknown
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Expected O, but got Unknown
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Expected O, but got Unknown
		//IL_00dd: 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_00f4: Expected O, but got Unknown
		//IL_00f4: 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_010b: Expected O, but got Unknown
		//IL_010d: Expected O, but got Unknown
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Expected O, but got Unknown
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Unknown result type (might be due to invalid IL or missing references)
		//IL_039e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0401: Unknown result type (might be due to invalid IL or missing references)
		//IL_0403: Unknown result type (might be due to invalid IL or missing references)
		//IL_0405: Unknown result type (might be due to invalid IL or missing references)
		_isPocketing = true;
		try
		{
			int num = _localPocket[_localPocket.Count - 1];
			if (_pendingRestore.Contains(num))
			{
				return;
			}
			if (_clientHostedItems.Contains(num))
			{
				if (HasPendingRequest(_pendingDropAcks, num))
				{
					SetHudMessage("Aguarde...");
					return;
				}
				int num2 = ++_nonce;
				PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
				Vector3 val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : Vector3.zero);
				Hashtable val3 = new Hashtable();
				((Dictionary<object, object>)val3).Add((object)"vid", (object)num);
				((Dictionary<object, object>)val3).Add((object)"nonce", (object)num2);
				((Dictionary<object, object>)val3).Add((object)"cpx", (object)val2.x);
				((Dictionary<object, object>)val3).Add((object)"cpy", (object)val2.y);
				((Dictionary<object, object>)val3).Add((object)"cpz", (object)val2.z);
				Hashtable val4 = val3;
				RaiseEventOptions val5 = new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				};
				PhotonNetwork.RaiseEvent((byte)74, (object)val4, val5, SendOptions.SendReliable);
				TrackPending(_pendingDropAcks, num2, num, "Drop");
				SetHudMessage("Aguarde...");
				int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
				QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] request drop actor=" + actorNumber + " viewID=" + num + " nonce=" + num2 + " clientPos=" + ((Vector3)(ref val2)).ToString("F2")));
				return;
			}
			GameObject val6 = FindPocketedObject(num);
			if ((Object)(object)val6 == (Object)null)
			{
				QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Item (key=" + num + ") nao encontrado — removido do bolso."));
				_localPocket.RemoveAt(_localPocket.Count - 1);
				_snapshots.Remove(num);
				_singleplayerObjects.Remove(num);
				PublishPocketedItems();
				return;
			}
			if (!_snapshots.TryGetValue(num, out var value))
			{
				QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Snapshot ausente para key=" + num + " — removido."));
				_localPocket.RemoveAt(_localPocket.Count - 1);
				_singleplayerObjects.Remove(num);
				PublishPocketedItems();
				return;
			}
			PlayerAvatar val7 = SemiFunc.PlayerAvatarLocal();
			bool flag = SemiFunc.PhysGrabberLocalIsGrabbing();
			if (flag && !QuickPocketPlugin.AutoDropIfHandsFull.Value)
			{
				QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Solte o que esta segurando antes de retirar do bolso.");
				return;
			}
			if (!TryFindSafeDropPosition(val7, flag, out var position, out var failReason))
			{
				SetHudMessage(failReason ?? "Sem espaco para soltar aqui.");
				return;
			}
			if (flag)
			{
				QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Maos ocupadas — item dropado proximo.");
			}
			Vector3 position2 = val6.transform.position;
			Vector3 playerPosAtDrop = (((Object)(object)val7 != (Object)null) ? ((Component)val7).transform.position : Vector3.zero);
			PocketOperations.RestoreSnapshot(val6, value, position);
			Rigidbody component = val6.GetComponent<Rigidbody>();
			ManualLogSource log = QuickPocketPlugin.Log;
			string[] obj = new string[12]
			{
				"[QP:Restore] item=",
				value.ItemName,
				" key=",
				num.ToString(),
				" original=",
				((Vector3)(ref position2)).ToString("F2"),
				" target=",
				((Vector3)(ref position)).ToString("F2"),
				" afterTransform=",
				null,
				null,
				null
			};
			Vector3 position3 = val6.transform.position;
			obj[9] = ((Vector3)(ref position3)).ToString("F2");
			obj[10] = " afterRb=";
			object obj2;
			if (!((Object)(object)component != (Object)null))
			{
				obj2 = "no-rb";
			}
			else
			{
				position3 = component.position;
				obj2 = ((Vector3)(ref position3)).ToString("F2");
			}
			obj[11] = (string)obj2;
			log.LogInfo((object)string.Concat(obj));
			_pendingRestore.Add(num);
			((MonoBehaviour)this).StartCoroutine(ConfirmAndFinalizeDrop(val6, value, num, position, playerPosAtDrop, position2));
		}
		finally
		{
			_isPocketing = false;
			_cooldownTimer = QuickPocketPlugin.PocketCooldown.Value;
		}
	}

	private void EnforcePocketState()
	{
		for (int num = _localPocket.Count - 1; num >= 0; num--)
		{
			int num2 = _localPocket[num];
			if (!_pendingRestore.Contains(num2))
			{
				GameObject val = FindPocketedObject(num2);
				ComponentSnapshot value3;
				if ((Object)(object)val == (Object)null)
				{
					if (_snapshots.TryGetValue(num2, out var value))
					{
						if ((Object)(object)value.MapValuableSpriteRenderer != (Object)null)
						{
							((Renderer)value.MapValuableSpriteRenderer).enabled = false;
							QuickPocketPlugin.Log.LogDebug((object)("[QP:MapMarker] item destroyed, marker hidden item=" + value.ItemName));
						}
						else if ((Object)(object)value.MapValuableMarker != (Object)null && (Object)(object)((Component)value.MapValuableMarker).gameObject != (Object)null)
						{
							((Component)value.MapValuableMarker).gameObject.SetActive(false);
							QuickPocketPlugin.Log.LogDebug((object)("[QP:MapMarker] item destroyed, marker hidden (SetActive fallback) item=" + value.ItemName));
						}
					}
					_localPocket.RemoveAt(num);
					_snapshots.Remove(num2);
					_singleplayerObjects.Remove(num2);
					PublishPocketedItems();
				}
				else if (_clientHostedItems.Contains(num2))
				{
					if (!_remoteSnapshots.TryGetValue(num2, out var value2))
					{
						int actorNumber = (SemiFunc.IsMultiplayer() ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
						value2 = SaveLocalSnapshotFor(val, num2, actorNumber);
						if (value2 != null)
						{
							_remoteSnapshots[num2] = value2;
						}
					}
					if (value2 != null && !PocketOperations.IsPocketStateConsistent(val, value2))
					{
						QuickPocketPlugin.Log.LogDebug((object)("[QP:EnforceState] viewID=" + num2 + " fixed=ClientHosted reason=OwnerAck"));
						int ownerActor = (SemiFunc.IsMultiplayer() ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
						PocketOperations.HidePocketedItemState(val, num2, ownerActor, HideMode.OwnerAck, "EnforceClientHosted", value2);
					}
				}
				else if (_snapshots.TryGetValue(num2, out value3) && !PocketOperations.IsPocketStateConsistent(val, value3))
				{
					QuickPocketPlugin.Log.LogDebug((object)("[QP:EnforceState] viewID=" + num2 + " fixed=Local reason=SnapshotInconsistent"));
					PocketOperations.HidePocketedItemState(val, num2, value3.ActorNumber, HideMode.Local, "EnforceLocal", value3);
				}
			}
		}
		EnforceHostedPocketState();
		EnforceRemotePocketState();
	}

	private void EnforceHostedPocketState()
	{
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			return;
		}
		foreach (KeyValuePair<int, List<(int, ComponentSnapshot)>> hostedPocket in _hostedPockets)
		{
			int key = hostedPocket.Key;
			List<(int, ComponentSnapshot)> value = hostedPocket.Value;
			for (int num = value.Count - 1; num >= 0; num--)
			{
				int item = value[num].Item1;
				ComponentSnapshot item2 = value[num].Item2;
				PhotonView val = PhotonView.Find(item);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && item2 != null && !PocketOperations.IsPocketStateConsistent(((Component)val).gameObject, item2))
				{
					QuickPocketPlugin.Log.LogDebug((object)("[QP:EnforceState] viewID=" + item + " fixed=HostHosted actor=" + key));
					PocketOperations.HidePocketedItemState(((Component)val).gameObject, item, key, HideMode.HostHosted, "EnforceHosted", item2);
				}
			}
		}
	}

	private void EnforceRemotePocketState()
	{
		foreach (KeyValuePair<int, List<int>> remoteHide in _remoteHides)
		{
			int key = remoteHide.Key;
			List<int> value = remoteHide.Value;
			for (int i = 0; i < value.Count; i++)
			{
				int num = value[i];
				if (_remoteSnapshots.TryGetValue(num, out var value2))
				{
					PhotonView val = PhotonView.Find(num);
					if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && !PocketOperations.IsPocketStateConsistent(((Component)val).gameObject, value2))
					{
						QuickPocketPlugin.Log.LogDebug((object)("[QP:EnforceState] viewID=" + num + " fixed=Remote actor=" + key));
						PocketOperations.HidePocketedItemState(((Component)val).gameObject, num, key, HideMode.Remote, "EnforceRemote", value2);
					}
				}
			}
		}
	}

	private void HideRemoteItem(int viewID, GameObject go)
	{
		HideRemoteItem(viewID, go, 0, HideMode.Remote, "LegacyRemoteHide");
	}

	private void RestoreWithSafeDefaults(GameObject go, Vector3 position)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		PocketOperations.RestorePocketedItemState(go, 0, 0, RestoreMode.SafeDefaults, position, "RestoreWithSafeDefaults");
	}

	private void RestoreRemoteVisuals(GameObject go)
	{
		int viewID = 0;
		PhotonView val = (((Object)(object)go != (Object)null) ? go.GetComponent<PhotonView>() : null);
		if ((Object)(object)val != (Object)null)
		{
			viewID = val.ViewID;
		}
		RestoreRemoteItem(viewID, go, 0, RestoreMode.Remote, null, "RestoreRemoteVisuals");
	}

	private void ProcessRemotePocketUpdate(int actorNumber, int[] newViewIDs)
	{
		bool flag = SemiFunc.IsMasterClientOrSingleplayer();
		_remoteHides.TryGetValue(actorNumber, out var value);
		value = value ?? new List<int>();
		List<int> list = ((newViewIDs != null) ? new List<int>(newViewIDs) : new List<int>());
		HashSet<int> hashSet = new HashSet<int>(value);
		HashSet<int> hashSet2 = new HashSet<int>(list);
		foreach (int item in hashSet2)
		{
			if (hashSet.Contains(item))
			{
				continue;
			}
			PhotonView val = PhotonView.Find(item);
			if ((Object)(object)val != (Object)null)
			{
				if (flag)
				{
					ComponentSnapshot componentSnapshot = FindHostedSnapshot(actorNumber, item);
					if (componentSnapshot == null)
					{
						componentSnapshot = SaveLocalSnapshotFor(((Component)val).gameObject, item, actorNumber);
					}
					PocketOperations.HidePocketedItemState(((Component)val).gameObject, item, actorNumber, HideMode.HostHosted, "RoomPropertiesHostAdd", componentSnapshot);
				}
				else
				{
					HideRemoteItem(item, ((Component)val).gameObject, actorNumber, HideMode.Remote, "RoomProperties");
				}
			}
			else
			{
				_pendingLateJoin[item] = Time.time + 10f;
				_pendingLateJoinActors[item] = actorNumber;
				QuickPocketPlugin.Log.LogDebug((object)("[QP] LateJoin: ViewID=" + item + " pendente."));
			}
		}
		foreach (int item2 in hashSet)
		{
			if (hashSet2.Contains(item2))
			{
				continue;
			}
			_pendingLateJoin.Remove(item2);
			_pendingLateJoinActors.Remove(item2);
			if (!flag)
			{
				PhotonView val2 = PhotonView.Find(item2);
				if ((Object)(object)val2 != (Object)null)
				{
					RestoreRemoteItem(item2, ((Component)val2).gameObject, actorNumber, RestoreMode.Remote, null, "RoomProperties");
				}
			}
		}
		if (!flag)
		{
			if (list.Count > 0)
			{
				_remoteHides[actorNumber] = list;
			}
			else
			{
				_remoteHides.Remove(actorNumber);
			}
		}
	}

	private void ProcessPendingLateJoin()
	{
		List<int> list = new List<int>();
		foreach (KeyValuePair<int, float> item in _pendingLateJoin)
		{
			if (Time.time > item.Value)
			{
				QuickPocketPlugin.Log.LogDebug((object)("[QP] LateJoin: timeout para ViewID=" + item.Key + " — desistindo."));
				list.Add(item.Key);
				continue;
			}
			PhotonView val = PhotonView.Find(item.Key);
			if ((Object)(object)val != (Object)null)
			{
				int value;
				int actorNumber = (_pendingLateJoinActors.TryGetValue(item.Key, out value) ? value : 0);
				HideRemoteItem(item.Key, ((Component)val).gameObject, actorNumber, HideMode.LateJoin, "LateJoin");
				list.Add(item.Key);
			}
		}
		foreach (int item2 in list)
		{
			_pendingLateJoin.Remove(item2);
			_pendingLateJoinActors.Remove(item2);
		}
	}

	private void ProcessLateJoin()
	{
		if (_lateJoinProcessed)
		{
			return;
		}
		_lateJoinProcessed = true;
		ReadHostLimit();
		if (!PhotonNetwork.InRoom)
		{
			return;
		}
		int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
		Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
		foreach (object key in ((Dictionary<object, object>)(object)customProperties).Keys)
		{
			string text = key as string;
			switch (text)
			{
			case null:
			case "QP_HostMaxSlots":
			case "QP_UseHostLimit":
				continue;
			}
			if (text.StartsWith("QP_") && int.TryParse(text.Substring(3), out var result) && result != actorNumber && customProperties[key] is int[] array && array.Length != 0)
			{
				ProcessRemotePocketUpdate(result, array);
				QuickPocketPlugin.Log.LogDebug((object)("[QP] LateJoin: actor=" + result + " tem " + array.Length + " item(s) pocketado(s)."));
			}
		}
	}

	private void PublishPocketedItems()
	{
		//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_0045: Expected O, but got Unknown
		//IL_0046: Expected O, but got Unknown
		if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom && QuickPocketPlugin.SyncPocketState.Value)
		{
			int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)val).Add((object)PropKeyForActor(actorNumber), (object)_localPocket.ToArray());
			Hashtable val2 = val;
			PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
		}
	}

	private void ClearLocalPocket(bool publishToRoom)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		//IL_0035: Expected O, but got Unknown
		if (publishToRoom && SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom)
		{
			int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)val).Add((object)PropKeyForActor(actorNumber), (object)new int[0]);
			Hashtable val2 = val;
			PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
		}
		foreach (int item in _localPocket)
		{
			_remoteSnapshots.Remove(item);
		}
		ClearPendingRequests("ClearLocalPocket", hudReset: true);
		_localPocket.Clear();
		_snapshots.Clear();
		_singleplayerObjects.Clear();
		_pendingRestore.Clear();
		_clientHostedItems.Clear();
		_isPocketing = false;
		_cooldownTimer = 0f;
		EligibilityChecker.ClearCache();
	}

	private void ClearAllState()
	{
		_localPocket.Clear();
		_snapshots.Clear();
		_singleplayerObjects.Clear();
		_pendingRestore.Clear();
		_remoteHides.Clear();
		_pendingLateJoin.Clear();
		_pendingLateJoinActors.Clear();
		_hostedPockets.Clear();
		_clientHostedItems.Clear();
		_remoteSnapshots.Clear();
		ClearPendingRequests("ClearAllState", hudReset: true);
		_nonce = 0;
		_isPocketing = false;
		_cooldownTimer = 0f;
		_limitSynced = false;
		_cachedEffectiveLimit = -1;
		_lateJoinProcessed = false;
		_hudGeneration++;
		_managerGeneration = _hudGeneration;
		_hudGameplayReady = false;
		_hudSuppressedForTransition = true;
		_runIsLevelTrueStreak = 0;
		_loadingAnimDone = false;
		_loadingUIWasSeen = false;
		EligibilityChecker.ClearCache();
		QuickPocketPlugin.Log.LogDebug((object)("[QuickPocket] Estado limpo. gen=" + _hudGeneration + " _hudGameplayReady=false _hudSuppressedForTransition=true"));
	}

	internal void HandleDeath(Vector3 deathPos)
	{
		//IL_0022: 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_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		if (_localPocket.Count == 0)
		{
			EligibilityChecker.ClearCache();
			return;
		}
		if (QuickPocketPlugin.DropOnDeath.Value)
		{
			Vector3 targetPosition = deathPos + Vector3.up * 0.5f;
			foreach (int item in _localPocket)
			{
				if (_clientHostedItems.Contains(item))
				{
					if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom)
					{
						SendHostedDropRequest(item, deathPos, "Death", trackPending: true);
					}
					continue;
				}
				GameObject val = FindPocketedObject(item);
				if (!((Object)(object)val == (Object)null) && _snapshots.TryGetValue(item, out var value))
				{
					PocketOperations.RestoreSnapshot(val, value, targetPosition);
				}
			}
			QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Morte: " + _localPocket.Count + " item(s) dropado(s)."));
		}
		else
		{
			QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Morte: estado limpo (DropOnDeath=false — itens restaurados pelos outros clientes).");
		}
		ClearLocalPocket(publishToRoom: true);
	}

	internal void HandleLevelChange()
	{
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		if (_hudSuppressedForTransition)
		{
			return;
		}
		_hudGeneration++;
		_managerGeneration = _hudGeneration;
		_hudGameplayReady = false;
		_hudSuppressedForTransition = true;
		_runIsLevelTrueStreak = 0;
		_loadingAnimDone = false;
		_loadingUIWasSeen = false;
		QuickPocketPlugin.Log.LogDebug((object)("[QP:HUDState] gen=" + _hudGeneration + " allowed=false reason=LevelChangeStart"));
		if (_localPocket.Count == 0)
		{
			EligibilityChecker.ClearCache();
			return;
		}
		SetHudMessage("Voce ainda tem itens no bolso!");
		QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Fase mudando com " + _localPocket.Count + " item(s) no bolso."));
		if (QuickPocketPlugin.DropOnLevelChange.Value)
		{
			Vector3 safeDropPosition = GetSafeDropPosition();
			foreach (int item in _localPocket)
			{
				if (_clientHostedItems.Contains(item))
				{
					if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom)
					{
						SendHostedDropRequest(item, safeDropPosition, "LevelChange", trackPending: true);
					}
					continue;
				}
				GameObject val = FindPocketedObject(item);
				if (!((Object)(object)val == (Object)null) && _snapshots.TryGetValue(item, out var value))
				{
					PocketOperations.RestoreSnapshot(val, value, safeDropPosition);
				}
			}
			QuickPocketPlugin.Log.LogInfo((object)("[QuickPocket] Fase mudou: " + _localPocket.Count + " item(s) dropado(s)."));
		}
		else
		{
			QuickPocketPlugin.Log.LogInfo((object)"[QuickPocket] Fase mudou: estado limpo (DropOnLevelChange=false).");
		}
		ClearLocalPocket(publishToRoom: true);
	}

	internal void HandleMainMenu()
	{
		QuickPocketPlugin.Log.LogDebug((object)"[QuickPocket] Retorno ao menu — limpando estado.");
		ClearAllState();
	}

	private bool ShouldRenderHud()
	{
		if (!QuickPocketPlugin.ShowPocketHUD.Value)
		{
			return false;
		}
		if (!_hasLocalPocketManager)
		{
			return false;
		}
		if (_managerGeneration != _hudGeneration)
		{
			return false;
		}
		if (_hudSuppressedForTransition)
		{
			return false;
		}
		if (!_hudGameplayReady)
		{
			return false;
		}
		if (!_cachedRunIsLevel)
		{
			return false;
		}
		if (_cachedIsLoading)
		{
			return false;
		}
		if (!_loadingAnimDone)
		{
			return false;
		}
		if ((Object)(object)SemiFunc.PlayerAvatarLocal() == (Object)null)
		{
			return false;
		}
		return true;
	}

	private static bool IsLoadingActive()
	{
		try
		{
			LoadingUI instance = LoadingUI.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if (_loadingUIAnimCompleted == null)
			{
				_loadingUIAnimCompleted = AccessTools.Field(typeof(LoadingUI), "levelAnimationCompleted");
			}
			if (_loadingUIAnimCompleted == null)
			{
				return false;
			}
			return !(bool)_loadingUIAnimCompleted.GetValue(instance);
		}
		catch
		{
			return false;
		}
	}

	internal static void OnLoadingStarted()
	{
		PocketManager instance = Instance;
		if (!((Object)(object)instance == (Object)null) && !instance._hudSuppressedForTransition)
		{
			instance._hudGameplayReady = false;
			instance._hudSuppressedForTransition = true;
			instance._runIsLevelTrueStreak = 0;
			instance._loadingAnimDone = false;
			instance._loadingUIWasSeen = false;
			QuickPocketPlugin.Log.LogDebug((object)("[QP:HUDState] gen=" + _hudGeneration + " allowed=false reason=StartLoading"));
		}
	}

	internal void OnLoadingAnimationComplete()
	{
		if (!((Object)(object)this != (Object)(object)Instance) && _managerGeneration == _hudGeneration)
		{
			_loadingAnimDone = true;
			_loadingAnimDoneTime = Time.time;
			QuickPocketPlugin.Log.LogDebug((object)("[QP:HUDState] gen=" + _hudGeneration + " loadingAnimDone=true reason=LevelAnimationComplete animDoneTime=" + _loadingAnimDoneTime.ToString("F1")));
		}
	}

	private static bool TrySemiRunIsLevel()
	{
		if (!_runIsLevelChecked)
		{
			_runIsLevelChecked = true;
			_runIsLevelMethod = AccessTools.Method(typeof(SemiFunc), "RunIsLevel", (Type[])null, (Type[])null);
			QuickPocketPlugin.Log.LogDebug((object)("[QuickPocket] SemiFunc.RunIsLevel(): " + ((_runIsLevelMethod != null) ? "encontrado." : "nao encontrado — HUD permanece OFF ate confirmacao.")));
		}
		if (_runIsLevelMethod == null)
		{
			return false;
		}
		try
		{
			return (bool)_runIsLevelMethod.Invoke(null, null);
		}
		catch
		{
			return false;
		}
	}

	private void OnGUI()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected O, but got Unknown
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)this != (Object)(object)Instance || !ShouldRenderHud())
		{
			return;
		}
		int effectiveLimit = GetEffectiveLimit();
		bool num = effectiveLimit < 0;
		int count = _localPocket.Count;
		GUIStyle val = new GUIStyle(GUI.skin.label)
		{
			fontSize = 14
		};
		val.normal.textColor = Color.white;
		GUIStyle val2 = val;
		GUIStyle val3 = new GUIStyle(val2);
		val3.normal.textColor = new Color(0f, 0f, 0f, 0.6f);
		GUIStyle val4 = val3;
		Color color = GUI.color;
		GUI.color = Color.white;
		string text = (num ? "QuickPocket: sync..." : ("QuickPocket: " + count + "/" + effectiveLimit));
		GUI.Label(new Rect(11f, (float)Screen.height - 29f, 400f, 24f), text, val4);
		GUI.Label(new Rect(10f, (float)Screen.height - 30f, 400f, 24f), text, val2);
		if (!string.IsNullOrEmpty(_hudActionMessage))
		{
			float num2 = 1f;
			if (!QuickPocketPlugin.HudAlwaysVisible.Value)
			{
				float num3 = Time.time - _hudActionMessageTime;
				float value = QuickPocketPlugin.HudFadeSeconds.Value;
				if (num3 >= value)
				{
					GUI.color = color;
					return;
				}
				float num4 = Mathf.Min(0.5f, value * 0.2f);
				float num5 = value - num3;
				if (num5 < num4)
				{
					num2 = Mathf.Clamp01(num5 / num4);
				}
			}
			GUI.color = new Color(1f, 1f, 1f, num2);
			GUI.Label(new Rect(11f, (float)Screen.height - 53f, 600f, 24f), _hudActionMessage, val4);
			GUI.Label(new Rect(10f, (float)Screen.height - 54f, 600f, 24f), _hudActionMessage, val2);
		}
		GUI.color = color;
	}

	internal int GetEffectiveLimit()
	{
		if (!SemiFunc.IsMultiplayer())
		{
			return Mathf.Clamp(QuickPocketPlugin.MaxPocketSlots.Value, 1, 8);
		}
		if (!_limitSynced)
		{
			return -1;
		}
		return _cachedEffectiveLimit;
	}

	private void ReadHostLimit()
	{
		if (!PhotonNetwork.InRoom)
		{
			return;
		}
		Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
		if (((Dictionary<object, object>)(object)customProperties).TryGetValue((object)"QP_UseHostLimit", out object value) && ((Dictionary<object, object>)(object)customProperties).TryGetValue((object)"QP_HostMaxSlots", out object value2))
		{
			bool flag = (bool)value;
			int num = (int)value2;
			if (flag && QuickPocketPlugin.UseHostPocketLimit.Value)
			{
				_cachedEffectiveLimit = Mathf.Clamp(num, 1, 8);
			}
			else
			{
				_cachedEffectiveLimit = Mathf.Clamp(QuickPocketPlugin.MaxPocketSlots.Value, 1, 8);
			}
			_limitSynced = true;
			QuickPocketPlugin.Log.LogDebug((object)("[QuickPocket] Limite efetivo: " + _cachedEffectiveLimit + " (hostMax=" + num + " useHost=" + flag + ")"));
		}
		else
		{
			_limitSynced = false;
			QuickPocketPlugin.Log.LogDebug((object)"[QuickPocket] Room Properties QP_Host* ainda nao disponiveis.");
		}
	}

	private Vector3 GetSafeDropPosition()
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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)
		PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
		if ((Object)(object)val != (Object)null)
		{
			return ((Component)val).transform.position + Vector3.up * 0.5f;
		}
		return new Vector3(0f, 2f, 0f);
	}

	private static void ClientHideMapValuable(int vid, string itemName)
	{
		PocketManager instance = Instance;
		PhotonView val = PhotonView.Find(vid);
		if ((Object)(object)instance != (Object)null && (Object)(object)val != (Object)null)
		{
			instance.HideRemoteItem(vid, ((Component)val).gameObject, SemiFunc.IsMultiplayer() ? PhotonNetwork.LocalPlayer.ActorNumber : 0, HideMode.OwnerAck, "ClientHideMapValuableLegacy");
		}
	}

	private static void ClientRestoreMapValuable(int vid, string itemName)
	{
		PocketManager instance = Instance;
		PhotonView val = PhotonView.Find(vid);
		if ((Object)(object)instance != (Object)null && (Object)(object)val != (Object)null)
		{
			instance.RestoreRemoteItem(vid, ((Component)val).gameObject, SemiFunc.IsMultiplayer() ? PhotonNetwork.LocalPlayer.ActorNumber : 0, RestoreMode.OwnerAck, null, "ClientRestoreMapValuableLegacy");
		}
	}

	public void OnEvent(EventData photonEvent)
	{
		if (photonEvent.CustomData == null)
		{
			return;
		}
		object customData = photonEvent.CustomData;
		Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null);
		if (val == null)
		{
			return;
		}
		switch (photonEvent.Code)
		{
		case 71:
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				HandleHostPocketRequest(val, photonEvent.Sender);
			}
			break;
		case 72:
			HandleClientPocketAck(val);
			break;
		case 73:
			HandleClientPocketDeny(val);
			break;
		case 74:
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				HandleHostDropRequest(val, photonEvent.Sender);
			}
			break;
		case 75:
			HandleClientDropAck(val);
			break;
		case 76:
			HandleClientDropDeny(val);
			break;
		}
	}

	private void HandleHostPocketRequest(Hashtable data, int senderActor)
	{
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Expected O, but got Unknown
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Expected O, but got Unknown
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Expected O, but got Unknown
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Expected O, but got Unknown
		//IL_026e: Expected O, but got Unknown
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Expected O, but got Unknown
		//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Expected O, but got Unknown
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Expected O, but got Unknown
		//IL_0316: Expected O, but got Unknown
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_0353: Expected O, but got Unknown
		//IL_0353: Unknown result type (might be due to invalid IL or missing references)
		//IL_0364: Expected O, but got Unknown
		//IL_0364: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0400: Unknown result type (might be due to invalid IL or missing references)
		//IL_0411: Expected O, but got Unknown
		//IL_0411: Unknown result type (might be due to invalid IL or missing references)
		//IL_0422: Expected O, but got Unknown
		//IL_0422: Unknown result type (might be due to invalid IL or missing references)
		//IL_0432: Expected O, but got Unknown
		//IL_0434: Expected O, but got Unknown
		//IL_043a: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Expected O, but got Unknown
		//IL_0381: Expected O, but got Unknown
		//IL_0387: Unknown result type (might be due to invalid IL or missing references)
		//IL_045d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0462: Unknown result type (might be due to invalid IL or missing references)
		//IL_0473: Expected O, but got Unknown
		//IL_0473: Unknown result type (might be due to invalid IL or missing references)
		//IL_0484: Expected O, but got Unknown
		//IL_0484: Unknown result type (might be due to invalid IL or missing references)
		//IL_0494: Expected O, but got Unknown
		//IL_0496: Expected O, but got Unknown
		//IL_049c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0528: Unknown result type (might be due to invalid IL or missing references)
		//IL_052d: Unknown result type (might be due to invalid IL or missing references)
		//IL_053c: Expected O, but got Unknown
		//IL_053e: Expected O, but got Unknown
		//IL_054d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Unknown result type (might be due to invalid IL or missing references)
		//IL_0563: Expected O, but got Unknown
		//IL_0563: Unknown result type (might be due to invalid IL or missing references)
		//IL_0574: Expected O, but got Unknown
		//IL_0574: Unknown result type (might be due to invalid IL or missing references)
		//IL_0586: Expected O, but got Unknown
		//IL_0588: Expected O, but got Unknown
		//IL_058e: Unknown result type (might be due to invalid IL or missing references)
		int num = (int)data[(object)"vid"];
		int num2 = (int)data[(object)"nonce"];
		if (((Dictionary<object, object>)(object)data).ContainsKey((object)"item"))
		{
			_ = (string)data[(object)"item"];
		}
		PhotonView val = PhotonView.Find(num);
		bool flag = (Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null;
		bool flag2 = false;
		foreach (KeyValuePair<int, List<(int, ComponentSnapshot)>> hostedPocket in _hostedPockets)
		{
			foreach (var item in hostedPocket.Value)
			{
				if (item.Item1 == num)
				{
					flag2 = true;
					break;
				}
			}
		}
		if (_localPocket.Contains(num))
		{
			flag2 = true;
		}
		int num3 = (_hostedPockets.ContainsKey(senderActor) ? _hostedPockets[senderActor].Count : 0);
		int num4 = Mathf.Clamp(QuickPocketPlugin.HostMaxOverride.Value, 1, 8);
		bool flag3 = num3 < num4;
		TryGetPositionByActorNumber(senderActor, out var found);
		bool flag4 = !_hudSuppressedForTransition && _cachedRunIsLevel;
		QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host received pocket actor=" + senderActor + " viewID=" + num + " exists=" + flag + " alreadyHosted=" + flag2 + " limitOK=" + flag3 + " actorFound=" + found + " hostReady=" + flag4));
		RaiseEventOptions val2 = new RaiseEventOptions();
		val2.TargetActors = new int[1] { senderActor };
		RaiseEventOptions val3 = val2;
		if (!flag || flag2 || !flag3 || !found || !flag4)
		{
			string text = ((!flag) ? "NotFound" : (flag2 ? "AlreadyPocketed" : ((!flag3) ? "LimitReached" : ((!found) ? "ActorNotFound" : "LevelChanging"))));
			Hashtable val4 = new Hashtable();
			((Dictionary<object, object>)val4).Add((object)"vid", (object)num);
			((Dictionary<object, object>)val4).Add((object)"nonce", (object)num2);
			((Dictionary<object, object>)val4).Add((object)"reason", (object)text);
			Hashtable val5 = val4;
			PhotonNetwork.RaiseEvent((byte)73, (object)val5, val3, SendOptions.SendReliable);
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host denied pocket actor=" + senderActor + " viewID=" + num + " reason=" + text));
			return;
		}
		PhysGrabObject component = ((Component)val).gameObject.GetComponent<PhysGrabObject>();
		if ((Object)(object)component == (Object)null)
		{
			Hashtable val6 = new Hashtable();
			((Dictionary<object, object>)val6).Add((object)"vid", (object)num);
			((Dictionary<object, object>)val6).Add((object)"nonce", (object)num2);
			((Dictionary<object, object>)val6).Add((object)"reason", (object)"NoPgo");
			Hashtable val7 = val6;
			PhotonNetwork.RaiseEvent((byte)73, (object)val7, val3, SendOptions.SendReliable);
			return;
		}
		EligibilityInfo eligibilityInfo = EligibilityChecker.Evaluate(component);
		if (!eligibilityInfo.Eligible)
		{
			Hashtable val8 = new Hashtable();
			((Dictionary<object, object>)val8).Add((object)"vid", (object)num);
			((Dictionary<object, object>)val8).Add((object)"nonce", (object)num2);
			((Dictionary<object, object>)val8).Add((object)"reason", (object)(eligibilityInfo.RejectReason ?? "NotEligible"));
			Hashtable val9 = val8;
			PhotonNetwork.RaiseEvent((byte)73, (object)val9, val3, SendOptions.SendReliable);
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host denied pocket actor=" + senderActor + " viewID=" + num + " reason=" + (eligibilityInfo.RejectReason ?? "NotEligible")));
			return;
		}
		ComponentSnapshot componentSnapshot = PocketOperations.SaveSnapshot(component, num, senderActor);
		if (!PocketOperations.ValidateSnapshot(componentSnapshot))
		{
			Hashtable val10 = new Hashtable();
			((Dictionary<object, object>)val10).Add((object)"vid", (object)num);
			((Dictionary<object, object>)val10).Add((object)"nonce", (object)num2);
			((Dictionary<object, object>)val10).Add((object)"reason", (object)"SnapshotFailed");
			Hashtable val11 = val10;
			PhotonNetwork.RaiseEvent((byte)73, (object)val11, val3, SendOptions.SendReliable);
			return;
		}
		if (!PocketOperations.HidePocketedItemState(((Component)val).gameObject, num, senderActor, HideMode.HostHosted, "HostPocketRequest", componentSnapshot))
		{
			Hashtable val12 = new Hashtable();
			((Dictionary<object, object>)val12).Add((object)"vid", (object)num);
			((Dictionary<object, object>)val12).Add((object)"nonce", (object)num2);
			((Dictionary<object, object>)val12).Add((object)"reason", (object)"HideFailed");
			Hashtable val13 = val12;
			PhotonNetwork.RaiseEvent((byte)73, (object)val13, val3, SendOptions.SendReliable);
			return;
		}
		if (!_hostedPockets.ContainsKey(senderActor))
		{
			_hostedPockets[senderActor] = new List<(int, ComponentSnapshot)>();
		}
		_hostedPockets[senderActor].Add((num, componentSnapshot));
		int[] array = new int[_hostedPockets[senderActor].Count];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = _hostedPockets[senderActor][i].vid;
		}
		Hashtable val14 = new Hashtable();
		((Dictionary<object, object>)val14).Add((object)PropKeyForActor(senderActor), (object)array);
		Hashtable val15 = val14;
		PhotonNetwork.CurrentRoom.SetCustomProperties(val15, (Hashtable)null, (WebFlags)null);
		Hashtable val16 = new Hashtable();
		((Dictionary<object, object>)val16).Add((object)"vid", (object)num);
		((Dictionary<object, object>)val16).Add((object)"nonce", (object)num2);
		((Dictionary<object, object>)val16).Add((object)"item", (object)componentSnapshot.ItemName);
		Hashtable val17 = val16;
		PhotonNetwork.RaiseEvent((byte)72, (object)val17, val3, SendOptions.SendReliable);
		QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host pocket actor=" + senderActor + " viewID=" + num + " item=" + componentSnapshot.ItemName + " result=ACK hostedCount=" + _hostedPockets[senderActor].Count));
	}

	private void HandleHostDropRequest(Hashtable data, int senderActor)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Expected O, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Expected O, but got Unknown
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Expected O, but got Unknown
		//IL_00cc: Expected O, but got Unknown
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Expected O, but got Unknown
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f1: Expected O, but got Unknown
		//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0301: Expected O, but got Unknown
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Expected O, but got Unknown
		//IL_0314: Expected O, but got Unknown
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0409: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_0486: Unknown result type (might be due to invalid IL or missing references)
		//IL_048b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ac: Expected O, but got Unknown
		//IL_03ae: Expected O, but got Unknown
		//IL_04a2: Expected O, but got Unknown
		//IL_04a4: Expected O, but got Unknown
		//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c9: Expected O, but got Unknown
		//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04da: Expected O, but got Unknown
		//IL_04da: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f1: Expected O, but got Unknown
		//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0508: Expected O, but got Unknown
		//IL_0508: Unknown result type (might be due to invalid IL or missing references)
		//IL_050e: Unknown result type (might be due to invalid IL or missing references)
		//IL_051f: Expected O, but got Unknown
		//IL_051f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0530: Expected O, but got Unknown
		//IL_0532: Expected O, but got Unknown
		//IL_0538: Unknown result type (might be due to invalid IL or missing references)
		int num = (int)data[(object)"vid"];
		int num2 = (int)data[(object)"nonce"];
		ComponentSnapshot componentSnapshot = null;
		int index = -1;
		if (_hostedPockets.TryGetValue(senderActor, out List<(int, ComponentSnapshot)> value))
		{
			for (int i = 0; i < value.Count; i++)
			{
				if (value[i].Item1 == num)
				{
					componentSnapshot = value[i].Item2;
					index = i;
					break;
				}
			}
		}
		RaiseEventOptions val = new RaiseEventOptions();
		val.TargetActors = new int[1] { senderActor };
		RaiseEventOptions val2 = val;
		if (componentSnapshot == null)
		{
			Hashtable val3 = new Hashtable();
			((Dictionary<object, object>)val3).Add((object)"vid", (object)num);
			((Dictionary<object, object>)val3).Add((object)"nonce", (object)num2);
			((Dictionary<object, object>)val3).Add((object)"reason", (object)"NotHosted");
			Hashtable val4 = val3;
			PhotonNetwork.RaiseEvent((byte)76, (object)val4, val2, SendOptions.SendReliable);
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host deny drop actor=" + senderActor + " viewID=" + num + " reason=NotHosted"));
			return;
		}
		bool found;
		Vector3 val5 = TryGetPositionByActorNumber(senderActor, out found);
		Vector3 val7;
		if (((Dictionary<object, object>)(object)data).ContainsKey((object)"cpx"))
		{
			float num3 = (float)data[(object)"cpx"];
			float num4 = (float)data[(object)"cpy"];
			float num5 = (float)data[(object)"cpz"];
			Vector3 val6 = default(Vector3);
			((Vector3)(ref val6))..ctor(num3, num4, num5);
			val7 = (found ? val5 : val6);
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host resolve actor=" + senderActor + " avatarFound=" + found + " avatarPos=" + ((Vector3)(ref val5)).ToString("F2") + " reqPos=" + ((Vector3)(ref val6)).ToString("F2") + " dist=" + Vector3.Distance(val5, val6).ToString("F2") + " base=" + (found ? "RemoteAvatar" : "RequestFallback")));
		}
		else
		{
			val7 = val5;
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host resolve actor=" + senderActor + " avatarFound=" + found + " avatarPos=" + ((Vector3)(ref val5)).ToString("F2") + " base=AvatarOnly"));
		}
		Vector3 val8 = val7 + Vector3.up * 0.5f;
		PhotonView val9 = PhotonView.Find(num);
		if ((Object)(object)val9 == (Object)null || (Object)(object)((Component)val9).gameObject == (Object)null)
		{
			Hashtable val10 = new Hashtable();
			((Dictionary<object, object>)val10).Add((object)"vid", (object)num);
			((Dictionary<object, object>)val10).Add((object)"nonce", (object)num2);
			((Dictionary<object, object>)val10).Add((object)"reason", (object)"ItemDestroyed");
			((Dictionary<object, object>)val10).Add((object)"clear", (object)true);
			Hashtable val11 = val10;
			PhotonNetwork.RaiseEvent((byte)76, (object)val11, val2, SendOptions.SendReliable);
			value.RemoveAt(index);
			if (value.Count == 0)
			{
				_hostedPockets.Remove(senderActor);
			}
			int[] array = (_hostedPockets.ContainsKey(senderActor) ? Array.ConvertAll(_hostedPockets[senderActor].ToArray(), ((int vid, ComponentSnapshot snap) e) => e.vid) : new int[0]);
			Hashtable val12 = new Hashtable();
			((Dictionary<object, object>)val12).Add((object)PropKeyForActor(senderActor), (object)((array.Length != 0) ? array : null));
			Hashtable val13 = val12;
			PhotonNetwork.CurrentRoom.SetCustomProperties(val13, (Hashtable)null, (WebFlags)null);
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host deny drop actor=" + senderActor + " viewID=" + num + " reason=ItemDestroyed clear=True"));
			return;
		}
		PocketOperations.RestorePocketedItemState(((Component)val9).gameObject, num, senderActor, RestoreMode.HostHosted, val8, "HostDropRequest", componentSnapshot);
		value.RemoveAt(index);
		if (value.Count == 0)
		{
			_hostedPockets.Remove(senderActor);
		}
		int[] array2 = (_hostedPockets.ContainsKey(senderActor) ? Array.ConvertAll(_hostedPockets[senderActor].ToArray(), ((int vid, ComponentSnapshot snap) e) => e.vid) : new int[0]);
		Hashtable val14 = new Hashtable();
		((Dictionary<object, object>)val14).Add((object)PropKeyForActor(senderActor), (object)((array2.Length != 0) ? array2 : null));
		Hashtable val15 = val14;
		PhotonNetwork.CurrentRoom.SetCustomProperties(val15, (Hashtable)null, (WebFlags)null);
		Hashtable val16 = new Hashtable();
		((Dictionary<object, object>)val16).Add((object)"vid", (object)num);
		((Dictionary<object, object>)val16).Add((object)"nonce", (object)num2);
		((Dictionary<object, object>)val16).Add((object)"px", (object)val8.x);
		((Dictionary<object, object>)val16).Add((object)"py", (object)val8.y);
		((Dictionary<object, object>)val16).Add((object)"pz", (object)val8.z);
		((Dictionary<object, object>)val16).Add((object)"item", (object)componentSnapshot.ItemName);
		Hashtable val17 = val16;
		PhotonNetwork.RaiseEvent((byte)75, (object)val17, val2, SendOptions.SendReliable);
		QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] host drop actor=" + senderActor + " viewID=" + num + " item=" + componentSnapshot.ItemName + " pos=" + ((Vector3)(ref val8)).ToString("F2") + " result=OK"));
	}

	private void HandleClientPocketAck(Hashtable data)
	{
		int num = (int)data[(object)"vid"];
		int key = (int)data[(object)"nonce"];
		string raw = (((Dictionary<object, object>)(object)data).ContainsKey((object)"item") ? ((string)data[(object)"item"]) : "?");
		if (!_pendingPocketAcks.ContainsKey(key))
		{
			return;
		}
		_pendingPocketAcks.Remove(key);
		if (!_localPocket.Contains(num))
		{
			_localPocket.Add(num);
			_clientHostedItems.Add(num);
			PhotonView val = PhotonView.Find(num);
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null)
			{
				HideRemoteItem(num, ((Component)val).gameObject, PhotonNetwork.LocalPlayer.ActorNumber, HideMode.OwnerAck, "ACK_POCKET");
			}
			else
			{
				_pendingLateJoin[num] = Time.time + 10f;
				_pendingLateJoinActors[num] = PhotonNetwork.LocalPlayer.ActorNumber;
			}
			int effectiveLimit = GetEffectiveLimit();
			SetHudMessage("Guardado: " + CleanItemName(raw) + " (" + _localPocket.Count + "/" + effectiveLimit + ")");
			int num2 = (SemiFunc.IsMultiplayer() ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] ack pocket actor=" + num2 + " viewID=" + num + " result=OK count=" + _localPocket.Count + "/" + effectiveLimit));
		}
	}

	private void HandleClientPocketDeny(Hashtable data)
	{
		int num = (int)data[(object)"vid"];
		int key = (int)data[(object)"nonce"];
		string text = (((Dictionary<object, object>)(object)data).ContainsKey((object)"reason") ? ((string)data[(object)"reason"]) : "?");
		_pendingPocketAcks.Remove(key);
		SetHudMessage("Nao foi possivel guardar: " + text);
		QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] deny pocket viewID=" + num + " reason=" + text));
	}

	private void HandleClientDropAck(Hashtable data)
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		int num = (int)data[(object)"vid"];
		int key = (int)data[(object)"nonce"];
		string raw = (((Dictionary<object, object>)(object)data).ContainsKey((object)"item") ? ((string)data[(object)"item"]) : "?");
		if (_pendingDropAcks.ContainsKey(key))
		{
			_pendingDropAcks.Remove(key);
			Vector3 zero = Vector3.zero;
			bool flag = ((Dictionary<object, object>)(object)data).ContainsKey((object)"px");
			if (flag)
			{
				((Vector3)(ref zero))..ctor((float)data[(object)"px"], (float)data[(object)"py"], (float)data[(object)"pz"]);
			}
			_localPocket.Remove(num);
			_clientHostedItems.Remove(num);
			PhotonView val = PhotonView.Find(num);
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null)
			{
				RestoreRemoteItem(num, ((Component)val).gameObject, PhotonNetwork.LocalPlayer.ActorNumber, RestoreMode.OwnerAck, flag ? new Vector3?(zero) : ((Vector3?)null), "ACK_DROP");
			}
			else
			{
				_remoteSnapshots.Remove(num);
			}
			int effectiveLimit = GetEffectiveLimit();
			int count = _localPocket.Count;
			SetHudMessage("Retirado: " + CleanItemName(raw) + " (" + count + "/" + effectiveLimit + ")");
			int num2 = (SemiFunc.IsMultiplayer() ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
			QuickPocketPlugin.Log.LogInfo((object)("[QP:MP] ack drop actor=" + num2 + " viewID=" + num + " result=OK finalPos=" + (flag ? ((Vector3)(ref zero)).ToString("F2") : "n/a") + " count=" + count + "/" + effectiveLimit));
		}
	}

	private void HandleClientDropDeny(Hashtable data)
	{
		int num = (int)data[(object)"vid"];
		int key = (int)data[(object)"nonce"];
		strin