Decompiled source of DeathChest v1.9.1

BepInEx/plugins/DeathChest/DeathChest.dll

Decompiled 10 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("DeathChest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DeathChest")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b8ff20b6-2efb-4726-91c3-fb3b0fc22a3e")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.robertomontanas.muck.deathchest", "Death Chest", "1.9.1")]
public class DeathChestPlugin : BaseUnityPlugin
{
	private class DroppedItem
	{
		public int ItemId;

		public int Amount;

		public int ObjectId;

		public DroppedItem(int itemId, int amount, int objectId)
		{
			ItemId = itemId;
			Amount = amount;
			ObjectId = objectId;
		}
	}

	private class DropBatch
	{
		public int ClientId;

		public float FirstDropTime;

		public float LastDropTime;

		public bool MultipleDrops;

		public readonly List<DroppedItem> Items = new List<DroppedItem>();

		public DropBatch(int clientId, float time)
		{
			ClientId = clientId;
			FirstDropTime = time;
			LastDropTime = time;
			MultipleDrops = false;
		}
	}

	private class ProtectedChest
	{
		public int ObjectId;

		public BuildDestruction BuildDestruction;

		public ProtectedChest(int objectId, BuildDestruction buildDestruction)
		{
			ObjectId = objectId;
			BuildDestruction = buildDestruction;
		}
	}

	private const string PluginGuid = "com.robertomontanas.muck.deathchest";

	private const string PluginName = "Death Chest";

	private const string PluginVersion = "1.9.1";

	private const float DeathTimeout = 2f;

	private const float DropBatchWindow = 0.05f;

	private const float FirstChestHeight = 1f;

	private const float SecondChestHeight = 2.75f;

	private const float DropRemovalDelay = 0.5f;

	private const int DropRemovalRetries = 2;

	private const float DropRemovalRetryDelay = 0.1f;

	private const int ProtectedDeathChestCount = 16;

	private const int DeathChestExtraHP = 10000;

	private const int ChestSize = 21;

	private static DeathChestPlugin Instance;

	private Harmony harmony;

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

	private readonly Queue<ProtectedChest> protectedDeathChests = new Queue<ProtectedChest>();

	private void Awake()
	{
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Expected O, but got Unknown
		Instance = this;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Death Chest v1.9.1");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Death Chest iniciado.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Modo actual: captura + preview + creación de cofres.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Protección de estabilidad: últimos " + 16 + " cofres."));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Protección contra mobs: activa.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Protección de daño de Death Chests: activa.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Destrucción de Chest mediante OnKill: no interceptada.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Death Chest HP extra: +" + 10000));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Eliminación de drops mediante ItemManager.PickupItem.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
		try
		{
			harmony = new Harmony("com.robertomontanas.muck.deathchest");
			InstallPatches();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hooks instalados correctamente.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Esperando drops y muertes...");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"ERROR instalando Death Chest:");
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
	}

	private void InstallPatches()
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Expected O, but got Unknown
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Expected O, but got Unknown
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Expected O, but got Unknown
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Expected O, but got Unknown
		//IL_0326: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Expected O, but got Unknown
		MethodInfo methodInfo = AccessTools.Method(typeof(ItemManager), "DropItem", new Type[4]
		{
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(int)
		}, (Type[])null);
		if (methodInfo == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ ItemManager.DropItem(int, int, int, int).");
			return;
		}
		harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(DeathChestPlugin), "ItemManagerDropItemPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Hook instalado: ItemManager.DropItem(...)");
		MethodInfo methodInfo2 = AccessTools.Method(typeof(ServerHandle), "PlayerDied", new Type[2]
		{
			typeof(int),
			typeof(Packet)
		}, (Type[])null);
		if (methodInfo2 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ ServerHandle.PlayerDied(int, Packet).");
			return;
		}
		harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(DeathChestPlugin), "ServerPlayerDiedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Hook instalado: ServerHandle.PlayerDied(...)");
		MethodInfo methodInfo3 = AccessTools.Method(typeof(Hitable), "Damage", new Type[4]
		{
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(Vector3)
		}, (Type[])null);
		if (methodInfo3 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ Hitable.Damage(int, int, int, Vector3).");
		}
		else
		{
			harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(DeathChestPlugin), "HitableDamagePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hook instalado: Hitable.Damage(...)");
		}
		MethodInfo methodInfo4 = AccessTools.Method(typeof(ChestManager), "UpdateChest", new Type[4]
		{
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(int)
		}, (Type[])null);
		if (methodInfo4 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ ChestManager.UpdateChest(int, int, int, int).");
		}
		else
		{
			harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(DeathChestPlugin), "ChestManagerUpdateChestPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hook instalado: ChestManager.UpdateChest(...)");
		}
		MethodInfo methodInfo5 = AccessTools.Method(typeof(MobServerEnemy), "FindNextPosition", Type.EmptyTypes, (Type[])null);
		if (methodInfo5 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ MobServerEnemy.FindNextPosition().");
		}
		else
		{
			harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(typeof(DeathChestPlugin), "MobServerEnemyFindNextPositionPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hook instalado: MobServerEnemy.FindNextPosition(...)");
		}
		MethodInfo methodInfo6 = AccessTools.Method(typeof(MobServerEnemy), "TryAttack", Type.EmptyTypes, (Type[])null);
		if (methodInfo6 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ MobServerEnemy.TryAttack().");
			return;
		}
		harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(typeof(DeathChestPlugin), "MobServerEnemyTryAttackPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Hook instalado: MobServerEnemy.TryAttack(...)");
	}

	private static bool HitableDamagePrefix(Hitable __instance, int newHp, int fromClient, int hitEffect, Vector3 pos)
	{
		if ((Object)(object)Instance == (Object)null)
		{
			return true;
		}
		if ((Object)(object)__instance == (Object)null)
		{
			return true;
		}
		try
		{
			HitableChest val = (HitableChest)(object)((__instance is HitableChest) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			int num = -1;
			try
			{
				num = ((Hitable)val).GetId();
			}
			catch (Exception)
			{
				num = -1;
			}
			if (!Instance.IsProtectedDeathChest(num))
			{
				return true;
			}
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[CHEST DAMAGE PROTECTION] Daño bloqueado. ChestID=" + num + " CurrentHP=" + __instance.hp + " RequestedHP=" + newHp));
			return false;
		}
		catch (Exception ex2)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)"[CHEST DAMAGE PROTECTION] Error interceptando Hitable.Damage:");
				((BaseUnityPlugin)Instance).Logger.LogError((object)ex2);
			}
			return true;
		}
	}

	private static void ChestManagerUpdateChestPostfix(int chestId, int cellId, int itemId, int amount)
	{
		if ((Object)(object)Instance == (Object)null)
		{
			return;
		}
		try
		{
			Instance.CheckProtectedChestAfterUpdate(chestId);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)"[CHEST CONTENT] Error comprobando Death Chest vacío:");
			((BaseUnityPlugin)Instance).Logger.LogError((object)ex);
		}
	}

	private void CheckProtectedChestAfterUpdate(int chestId)
	{
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		if (!IsProtectedDeathChest(chestId))
		{
			return;
		}
		ChestManager chestManager = GetChestManager();
		if ((Object)(object)chestManager == (Object)null || chestManager.chests == null)
		{
			return;
		}
		if (!chestManager.chests.TryGetValue(chestId, out var value))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[CHEST CONTENT] Death Chest protegido ya no existe en ChestManager. ChestID=" + chestId));
			RemoveProtectedDeathChest(chestId);
		}
		else
		{
			if (ChestHasContents(value))
			{
				return;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST CONTENT] Death Chest quedó vacío. ChestID=" + chestId + ". Eliminando protección."));
			RemoveProtectedDeathChest(chestId);
			HitableChest val = GetChestFromTransform(((Component)value).transform);
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)value).GetComponentInParent<HitableChest>();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)value).GetComponentInChildren<HitableChest>(true);
			}
			if (!((Object)(object)val == (Object)null))
			{
				try
				{
					((Hitable)val).KillObject(Vector3.zero);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST CONTENT] ChestID=" + chestId + " destruido porque quedó vacío."));
					return;
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST CONTENT] Error destruyendo ChestID=" + chestId + ":"));
					((BaseUnityPlugin)this).Logger.LogError((object)ex);
					return;
				}
			}
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[CHEST CONTENT] No se encontró HitableChest para ChestID=" + chestId));
		}
	}

	private void RemoveProtectedDeathChest(int objectId)
	{
		if (protectedDeathChests.Count == 0)
		{
			return;
		}
		Queue<ProtectedChest> queue = new Queue<ProtectedChest>();
		bool flag = false;
		while (protectedDeathChests.Count > 0)
		{
			ProtectedChest protectedChest = protectedDeathChests.Dequeue();
			if (protectedChest != null)
			{
				if (protectedChest.ObjectId == objectId)
				{
					flag = true;
				}
				else
				{
					queue.Enqueue(protectedChest);
				}
			}
		}
		while (queue.Count > 0)
		{
			protectedDeathChests.Enqueue(queue.Dequeue());
		}
		if (flag)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[STABILITY] Death Chest eliminado de la protección. ObjectID=" + objectId + " ProtectedCount=" + protectedDeathChests.Count));
		}
	}

	private static void MobServerEnemyFindNextPositionPostfix(MobServerEnemy __instance, ref Vector3 __result)
	{
		//IL_00b1: 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)
		if ((Object)(object)Instance == (Object)null || (Object)(object)__instance == (Object)null)
		{
			return;
		}
		try
		{
			Mob component = ((Component)__instance).GetComponent<Mob>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.target == (Object)null || !Instance.IsChestTarget(component.target))
			{
				return;
			}
			HitableChest chestFromTransform = Instance.GetChestFromTransform(component.target);
			int num = -1;
			if ((Object)(object)chestFromTransform != (Object)null)
			{
				try
				{
					num = ((Hitable)chestFromTransform).GetId();
				}
				catch (Exception)
				{
					num = -1;
				}
			}
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[MOB PROTECTION] Mob intentó seleccionar un Chest. Objetivo cancelado. ChestID=" + num));
			component.target = null;
			component.targetPlayerId = -1;
			__result = Vector3.zero;
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)"[MOB PROTECTION] Error en FindNextPosition:");
			((BaseUnityPlugin)Instance).Logger.LogError((object)ex2);
		}
	}

	private static bool MobServerEnemyTryAttackPrefix(MobServerEnemy __instance)
	{
		if ((Object)(object)Instance == (Object)null)
		{
			return true;
		}
		if ((Object)(object)__instance == (Object)null)
		{
			return true;
		}
		try
		{
			Mob component = ((Component)__instance).GetComponent<Mob>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			if ((Object)(object)component.target == (Object)null)
			{
				return true;
			}
			if (!Instance.IsChestTarget(component.target))
			{
				return true;
			}
			HitableChest chestFromTransform = Instance.GetChestFromTransform(component.target);
			int num = -1;
			if ((Object)(object)chestFromTransform != (Object)null)
			{
				try
				{
					num = ((Hitable)chestFromTransform).GetId();
				}
				catch (Exception)
				{
					num = -1;
				}
			}
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[MOB PROTECTION] Ataque contra Chest bloqueado. ChestID=" + num));
			component.target = null;
			component.targetPlayerId = -1;
			return false;
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)"[MOB PROTECTION] Error en TryAttack:");
			((BaseUnityPlugin)Instance).Logger.LogError((object)ex2);
			return true;
		}
	}

	private bool IsChestTarget(Transform target)
	{
		if ((Object)(object)target == (Object)null)
		{
			return false;
		}
		if ((Object)(object)((Component)target).GetComponent<HitableChest>() != (Object)null)
		{
			return true;
		}
		if ((Object)(object)((Component)target).GetComponentInChildren<HitableChest>(true) != (Object)null)
		{
			return true;
		}
		if ((Object)(object)((Component)target).GetComponentInParent<HitableChest>() != (Object)null)
		{
			return true;
		}
		return false;
	}

	private HitableChest GetChestFromTransform(Transform target)
	{
		if ((Object)(object)target == (Object)null)
		{
			return null;
		}
		HitableChest component = ((Component)target).GetComponent<HitableChest>();
		if ((Object)(object)component != (Object)null)
		{
			return component;
		}
		component = ((Component)target).GetComponentInChildren<HitableChest>(true);
		if ((Object)(object)component != (Object)null)
		{
			return component;
		}
		return ((Component)target).GetComponentInParent<HitableChest>();
	}

	private bool IsProtectedDeathChest(int objectId)
	{
		foreach (ProtectedChest protectedDeathChest in protectedDeathChests)
		{
			if (protectedDeathChest != null && protectedDeathChest.ObjectId == objectId)
			{
				return true;
			}
		}
		return false;
	}

	private bool ChestHasContents(Chest chest)
	{
		if ((Object)(object)chest == (Object)null)
		{
			return false;
		}
		if (chest.cells == null)
		{
			return false;
		}
		InventoryItem[] cells = chest.cells;
		foreach (InventoryItem val in cells)
		{
			if ((Object)(object)val != (Object)null && val.amount > 0)
			{
				return true;
			}
		}
		return false;
	}

	private static void ItemManagerDropItemPrefix(int fromClient, int itemId, int amount, int objectID)
	{
		if ((Object)(object)Instance == (Object)null)
		{
			return;
		}
		try
		{
			Instance.RegisterDrop(fromClient, itemId, amount, objectID);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)"ERROR capturando ItemManager.DropItem:");
			((BaseUnityPlugin)Instance).Logger.LogError((object)ex);
		}
	}

	private void RegisterDrop(int clientId, int itemId, int amount, int objectId)
	{
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (pendingDrops.TryGetValue(clientId, out var value))
		{
			float num = realtimeSinceStartup - value.LastDropTime;
			if (num > 0.05f)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP BATCH RESET] ClientID=" + clientId + " Gap=" + (num * 1000f).ToString("0.000") + "ms"));
				pendingDrops.Remove(clientId);
				value = null;
			}
			else
			{
				value.MultipleDrops = true;
				value.LastDropTime = realtimeSinceStartup;
			}
		}
		if (!pendingDrops.TryGetValue(clientId, out var value2))
		{
			value2 = new DropBatch(clientId, realtimeSinceStartup);
			pendingDrops.Add(clientId, value2);
		}
		DroppedItem item = new DroppedItem(itemId, amount, objectId);
		value2.Items.Add(item);
		value2.LastDropTime = realtimeSinceStartup;
		string itemName = GetItemName(itemId);
		float num2 = realtimeSinceStartup - value2.FirstDropTime;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP] ClientID=" + clientId + " ItemID=" + itemId + " ItemName=\"" + itemName + "\" Amount=" + amount + " ObjectID=" + objectId + " BatchDrops=" + value2.Items.Count + " SinceFirstDrop=" + (num2 * 1000f).ToString("0.000") + "ms"));
	}

	private static void ServerPlayerDiedPostfix(int fromClient, Packet packet)
	{
		if ((Object)(object)Instance == (Object)null)
		{
			return;
		}
		try
		{
			Instance.ProcessDeath(fromClient);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)("ERROR procesando muerte de ClientID=" + fromClient + ":"));
			((BaseUnityPlugin)Instance).Logger.LogError((object)ex);
		}
	}

	private void ProcessDeath(int clientId)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] ClientID=" + clientId));
		Vector3 gravePosition;
		try
		{
			GameManager gameManager = GetGameManager();
			if ((Object)(object)gameManager == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[DEATH] No se pudo obtener GameManager.");
				return;
			}
			gravePosition = gameManager.GetGravePosition(clientId);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"No se pudo obtener la posición de la tumba.");
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] GravePosition=" + FormatVector3(gravePosition)));
		if (!pendingDrops.TryGetValue(clientId, out var value))
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[DEATH] No existen drops pendientes para este jugador.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
			return;
		}
		float num = realtimeSinceStartup - value.FirstDropTime;
		float num2 = realtimeSinceStartup - value.LastDropTime;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] FirstDropAgo=" + (num * 1000f).ToString("0.000") + "ms"));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] LastDropAgo=" + (num2 * 1000f).ToString("0.000") + "ms"));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] Drops capturados=" + value.Items.Count));
		if (!value.MultipleDrops)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[DEATH] Solo había un drop.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[DEATH] La tanda NO se considera Death Chest.");
			pendingDrops.Remove(clientId);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
		}
		else if (num > 2f)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[DEATH] La tanda de drops es demasiado antigua.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] Límite=" + 2f.ToString("0.00") + "s"));
			pendingDrops.Remove(clientId);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
		}
		else
		{
			PrintDeathChestPreview(clientId, value);
			CreateDeathChests(clientId, gravePosition, value, realtimeSinceStartup);
			pendingDrops.Remove(clientId);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"========================================");
		}
	}

	private void PrintDeathChestPreview(int clientId, DropBatch batch)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"----------------------------------------");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("DEATH CHEST PREVIEW — ClientID=" + clientId));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Cantidad de items=" + batch.Items.Count));
		for (int i = 0; i < batch.Items.Count; i++)
		{
			DroppedItem droppedItem = batch.Items[i];
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[" + i + "] ItemID=" + droppedItem.ItemId + " Name=\"" + GetItemName(droppedItem.ItemId) + "\" Amount=" + droppedItem.Amount + " ObjectID=" + droppedItem.ObjectId));
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"----------------------------------------");
	}

	private void CreateDeathChests(int clientId, Vector3 gravePosition, DropBatch batch, float deathTime)
	{
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		int num = FindChestItemId();
		if (num < 0)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] No se encontró un InventoryItem de tipo Storage con Chest.");
			return;
		}
		ItemManager itemManager = GetItemManager();
		if ((Object)(object)itemManager == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] No se pudo recuperar ItemManager.");
			return;
		}
		if (itemManager.allItems == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] ItemManager.allItems es null.");
			return;
		}
		if (!itemManager.allItems.TryGetValue(num, out var value))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST] ItemID=" + num + " no existe en ItemManager.allItems."));
			return;
		}
		if ((Object)(object)value == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] El InventoryItem Chest es null.");
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST] Storage encontrado: ItemID=" + num + " Name=\"" + value.name + "\""));
		Vector3 val = gravePosition + Vector3.up * 1f;
		int num2 = CreateChest(clientId, num, val);
		if (num2 < 0)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] Falló la creación del Chest #1.");
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST] Chest #1 creado. ObjectID=" + num2 + " Position=" + FormatVector3(val)));
		Vector3 val2 = val + Vector3.up * 2.75f;
		int num3 = CreateChest(clientId, num, val2);
		if (num3 < 0)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] Falló la creación del Chest #2.");
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST] Chest #2 creado. ObjectID=" + num3 + " Position=" + FormatVector3(val2)));
		try
		{
			ServerSend.SendBuild(clientId, num, num2, val, 0);
			ServerSend.SendBuild(clientId, num, num3, val2, 0);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[CHEST] SendBuild enviado para ambos cofres.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] Error enviando SendBuild:");
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			return;
		}
		((MonoBehaviour)this).StartCoroutine(FillChestsNextFrame(clientId, num2, num3, batch, deathTime));
	}

	private int CreateChest(int clientId, int chestItemId, Vector3 position)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			ResourceManager resourceManager = GetResourceManager();
			if ((Object)(object)resourceManager == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] No se pudo recuperar ResourceManager.");
				return -1;
			}
			BuildManager buildManager = GetBuildManager();
			if ((Object)(object)buildManager == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] No se pudo recuperar BuildManager.");
				return -1;
			}
			int nextId = resourceManager.GetNextId();
			GameObject val = buildManager.BuildItem(clientId, chestItemId, nextId, position, 0);
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST] BuildItem devolvió null. ObjectID=" + nextId));
				return -1;
			}
			Hitable val2 = val.GetComponent<Hitable>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.GetComponentInChildren<Hitable>(true);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				int hp = val2.hp;
				int maxHp = val2.maxHp;
				Hitable obj = val2;
				obj.hp += 10000;
				Hitable obj2 = val2;
				obj2.maxHp += 10000;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST HP] ObjectID=" + nextId + " HP=" + hp + " -> " + val2.hp + " MaxHP=" + maxHp + " -> " + val2.maxHp));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[CHEST HP] No se encontró Hitable para ObjectID=" + nextId));
			}
			ProtectDeathChest(nextId, val);
			return nextId;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST] Error creando Chest: " + ex));
			return -1;
		}
	}

	private void ProtectDeathChest(int objectId, GameObject chestObject)
	{
		if ((Object)(object)chestObject == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[STABILITY] ObjectID=" + objectId + " no tiene GameObject."));
			return;
		}
		BuildDestruction val = chestObject.GetComponent<BuildDestruction>();
		if ((Object)(object)val == (Object)null)
		{
			val = chestObject.GetComponentInChildren<BuildDestruction>(true);
		}
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[STABILITY] ObjectID=" + objectId + " no tiene BuildDestruction."));
			protectedDeathChests.Enqueue(new ProtectedChest(objectId, null));
			while (protectedDeathChests.Count > 16)
			{
				ProtectedChest protectedChest = protectedDeathChests.Dequeue();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[STABILITY] ObjectID=" + protectedChest.ObjectId + " dejó de estar dentro de los últimos " + 16 + " Death Chests protegidos."));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[STABILITY] ObjectID=" + objectId + " protegido mediante ObjectID aunque no tenga BuildDestruction."));
			return;
		}
		val.connectedToGround = true;
		val.directlyGrounded = true;
		protectedDeathChests.Enqueue(new ProtectedChest(objectId, val));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[STABILITY] Death Chest protegido. ObjectID=" + objectId + " ConnectedToGround=true DirectlyGrounded=true ProtectedCount=" + protectedDeathChests.Count));
		while (protectedDeathChests.Count > 16)
		{
			ProtectedChest protectedChest2 = protectedDeathChests.Dequeue();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[STABILITY] ObjectID=" + protectedChest2.ObjectId + " dejó de estar dentro de los últimos " + 16 + " Death Chests protegidos."));
		}
	}

	private void MaintainProtectedDeathChests()
	{
		if (protectedDeathChests.Count == 0)
		{
			return;
		}
		foreach (ProtectedChest protectedDeathChest in protectedDeathChests)
		{
			if (protectedDeathChest == null)
			{
				continue;
			}
			BuildDestruction buildDestruction = protectedDeathChest.BuildDestruction;
			if (!((Object)(object)buildDestruction == (Object)null))
			{
				try
				{
					buildDestruction.connectedToGround = true;
					buildDestruction.directlyGrounded = true;
				}
				catch (Exception)
				{
				}
			}
		}
	}

	private IEnumerator FillChestsNextFrame(int clientId, int chestId1, int chestId2, DropBatch batch, float deathTime)
	{
		yield return null;
		ChestManager chestManager = GetChestManager();
		if ((Object)(object)chestManager == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST CONTENT] No se pudo recuperar ChestManager.");
			yield break;
		}
		if (chestManager.chests == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST CONTENT] ChestManager.chests es null.");
			yield break;
		}
		if (!chestManager.chests.ContainsKey(chestId1))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST CONTENT] Chest " + chestId1 + " no existe en ChestManager."));
			yield break;
		}
		if (!chestManager.chests.ContainsKey(chestId2))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST CONTENT] Chest " + chestId2 + " no existe en ChestManager."));
			yield break;
		}
		List<int> storedObjectIds = new List<int>();
		int num = 0;
		foreach (DroppedItem item in batch.Items)
		{
			int num2;
			int num3;
			if (num < 21)
			{
				num2 = chestId1;
				num3 = num;
			}
			else
			{
				int num4 = num - 21;
				if (num4 >= 21)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[CHEST CONTENT] No hay espacio para ItemID=" + item.ItemId + " Amount=" + item.Amount + " ObjectID=" + item.ObjectId + ". El item permanece como drop original."));
					num++;
					continue;
				}
				num2 = chestId2;
				num3 = num4;
			}
			bool flag = false;
			try
			{
				chestManager.UpdateChest(num2, num3, item.ItemId, item.Amount);
				ServerSend.UpdateChest(clientId, num2, num3, item.ItemId, item.Amount);
				flag = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST CONTENT] ChestID=" + num2 + " Cell=" + num3 + " ItemID=" + item.ItemId + " Name=\"" + GetItemName(item.ItemId) + "\" Amount=" + item.Amount + " ObjectID=" + item.ObjectId));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST CONTENT] Error guardando ItemID=" + item.ItemId + " ObjectID=" + item.ObjectId + ":"));
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
			if (flag)
			{
				storedObjectIds.Add(item.ObjectId);
			}
			num++;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST CONTENT] Finalizado. Items procesados=" + Math.Min(batch.Items.Count, 42) + " Items almacenados=" + storedObjectIds.Count));
		float num5 = Time.realtimeSinceStartup - deathTime;
		float num6 = 0.5f - num5;
		if (num6 > 0f)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Esperando " + (num6 * 1000f).ToString("0.000") + "ms antes de eliminar los drops originales."));
			yield return (object)new WaitForSeconds(num6);
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Iniciando eliminación. Tiempo desde muerte=" + ((Time.realtimeSinceStartup - deathTime) * 1000f).ToString("0.000") + "ms"));
		yield return ((MonoBehaviour)this).StartCoroutine(RemoveOriginalDropsWithRetries(clientId, storedObjectIds));
	}

	private IEnumerator RemoveOriginalDropsWithRetries(int clientId, List<int> objectIds)
	{
		if (objectIds == null || objectIds.Count == 0)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[DROP REMOVE] No hay drops para eliminar.");
			yield break;
		}
		HashSet<int> uniqueObjectIds = new HashSet<int>(objectIds);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Objetos a eliminar=" + uniqueObjectIds.Count));
		int removed = 0;
		int alreadyMissing = 0;
		int failed = 0;
		foreach (int objectId in uniqueObjectIds)
		{
			bool removedSuccessfully = false;
			bool neverFound = true;
			int totalAttempts = 3;
			for (int attempt = 0; attempt < totalAttempts; attempt++)
			{
				ItemManager itemManager = GetItemManager();
				if ((Object)(object)itemManager == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Attempt=" + (attempt + 1) + "/" + totalAttempts + " ObjectID=" + objectId + " ItemManager no disponible."));
					if (attempt < 2)
					{
						yield return (object)new WaitForSeconds(0.1f);
					}
					continue;
				}
				if (itemManager.list == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Attempt=" + (attempt + 1) + "/" + totalAttempts + " ObjectID=" + objectId + " ItemManager.list es null."));
					if (attempt < 2)
					{
						yield return (object)new WaitForSeconds(0.1f);
					}
					continue;
				}
				if (!itemManager.list.ContainsKey(objectId))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Attempt=" + (attempt + 1) + "/" + totalAttempts + " ObjectID=" + objectId + " no existe."));
					if (attempt < 2)
					{
						yield return (object)new WaitForSeconds(0.1f);
					}
					continue;
				}
				neverFound = false;
				try
				{
					if (itemManager.PickupItem(objectId))
					{
						ServerSend.PickupItem(clientId, objectId);
						removedSuccessfully = true;
						removed++;
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] ObjectID=" + objectId + " eliminado mediante ItemManager.PickupItem(). Attempt=" + (attempt + 1) + "/" + totalAttempts));
						break;
					}
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Attempt=" + (attempt + 1) + "/" + totalAttempts + " ObjectID=" + objectId + " PickupItem devolvió false."));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Attempt=" + (attempt + 1) + "/" + totalAttempts + " ObjectID=" + objectId + " falló: " + ex.Message));
				}
				if (attempt < 2)
				{
					yield return (object)new WaitForSeconds(0.1f);
				}
			}
			if (!removedSuccessfully)
			{
				if (neverFound)
				{
					alreadyMissing++;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] ObjectID=" + objectId + " no apareció después de " + totalAttempts + " intentos."));
				}
				else
				{
					failed++;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] ObjectID=" + objectId + " no pudo eliminarse después de " + totalAttempts + " intentos."));
				}
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"----------------------------------------");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Resultado para ClientID=" + clientId));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Objetos únicos=" + uniqueObjectIds.Count));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Eliminados=" + removed));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] No encontrados=" + alreadyMissing));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Fallidos=" + failed));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"----------------------------------------");
	}

	private int FindChestItemId()
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Invalid comparison between Unknown and I4
		ItemManager itemManager = GetItemManager();
		if ((Object)(object)itemManager == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST SEARCH] No se pudo recuperar ItemManager.");
			return -1;
		}
		if (itemManager.allItems == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST SEARCH] ItemManager.allItems es null.");
			return -1;
		}
		foreach (KeyValuePair<int, InventoryItem> allItem in itemManager.allItems)
		{
			InventoryItem value = allItem.Value;
			if (!((Object)(object)value == (Object)null) && (int)value.type == 6 && !((Object)(object)value.prefab == (Object)null) && (Object)(object)value.prefab.GetComponentInChildren<Chest>(true) != (Object)null)
			{
				return allItem.Key;
			}
		}
		return -1;
	}

	private string GetItemName(int itemId)
	{
		try
		{
			ItemManager itemManager = GetItemManager();
			if ((Object)(object)itemManager == (Object)null)
			{
				return "<ItemManager null>";
			}
			if (itemManager.allItems == null)
			{
				return "<allItems null>";
			}
			if (!itemManager.allItems.TryGetValue(itemId, out var value))
			{
				return "<ID desconocido>";
			}
			if ((Object)(object)value == (Object)null)
			{
				return "<InventoryItem null>";
			}
			return value.name;
		}
		catch (Exception)
		{
			return "<error>";
		}
	}

	private ItemManager GetItemManager()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		Scene scene;
		try
		{
			if ((Object)(object)ItemManager.Instance != (Object)null && (Object)(object)((Component)ItemManager.Instance).gameObject != (Object)null)
			{
				scene = ((Component)ItemManager.Instance).gameObject.scene;
				if (((Scene)(ref scene)).IsValid())
				{
					return ItemManager.Instance;
				}
			}
		}
		catch (Exception)
		{
		}
		try
		{
			ItemManager[] array = Resources.FindObjectsOfTypeAll<ItemManager>();
			foreach (ItemManager val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return val;
					}
				}
			}
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("[MANAGER] Error buscando ItemManager: " + ex2.Message));
		}
		return null;
	}

	private ResourceManager GetResourceManager()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		Scene scene;
		try
		{
			if ((Object)(object)ResourceManager.Instance != (Object)null && (Object)(object)((Component)ResourceManager.Instance).gameObject != (Object)null)
			{
				scene = ((Component)ResourceManager.Instance).gameObject.scene;
				if (((Scene)(ref scene)).IsValid())
				{
					return ResourceManager.Instance;
				}
			}
		}
		catch (Exception)
		{
		}
		try
		{
			ResourceManager[] array = Resources.FindObjectsOfTypeAll<ResourceManager>();
			foreach (ResourceManager val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return val;
					}
				}
			}
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("[MANAGER] Error buscando ResourceManager: " + ex2.Message));
		}
		return null;
	}

	private BuildManager GetBuildManager()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		Scene scene;
		try
		{
			if ((Object)(object)BuildManager.Instance != (Object)null && (Object)(object)((Component)BuildManager.Instance).gameObject != (Object)null)
			{
				scene = ((Component)BuildManager.Instance).gameObject.scene;
				if (((Scene)(ref scene)).IsValid())
				{
					return BuildManager.Instance;
				}
			}
		}
		catch (Exception)
		{
		}
		try
		{
			BuildManager[] array = Resources.FindObjectsOfTypeAll<BuildManager>();
			foreach (BuildManager val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return val;
					}
				}
			}
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("[MANAGER] Error buscando BuildManager: " + ex2.Message));
		}
		return null;
	}

	private ChestManager GetChestManager()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		Scene scene;
		try
		{
			if ((Object)(object)ChestManager.Instance != (Object)null && (Object)(object)((Component)ChestManager.Instance).gameObject != (Object)null)
			{
				scene = ((Component)ChestManager.Instance).gameObject.scene;
				if (((Scene)(ref scene)).IsValid())
				{
					return ChestManager.Instance;
				}
			}
		}
		catch (Exception)
		{
		}
		try
		{
			ChestManager[] array = Resources.FindObjectsOfTypeAll<ChestManager>();
			foreach (ChestManager val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return val;
					}
				}
			}
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("[MANAGER] Error buscando ChestManager: " + ex2.Message));
		}
		return null;
	}

	private GameManager GetGameManager()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		Scene scene;
		try
		{
			if ((Object)(object)GameManager.instance != (Object)null && (Object)(object)((Component)GameManager.instance).gameObject != (Object)null)
			{
				scene = ((Component)GameManager.instance).gameObject.scene;
				if (((Scene)(ref scene)).IsValid())
				{
					return GameManager.instance;
				}
			}
		}
		catch (Exception)
		{
		}
		try
		{
			GameManager[] array = Resources.FindObjectsOfTypeAll<GameManager>();
			foreach (GameManager val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return val;
					}
				}
			}
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("[MANAGER] Error buscando GameManager: " + ex2.Message));
		}
		return null;
	}

	private void Update()
	{
		MaintainProtectedDeathChests();
		if (pendingDrops.Count == 0)
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		List<int> list = new List<int>();
		foreach (KeyValuePair<int, DropBatch> pendingDrop in pendingDrops)
		{
			DropBatch value = pendingDrop.Value;
			if (realtimeSinceStartup - value.FirstDropTime > 2f)
			{
				list.Add(pendingDrop.Key);
			}
		}
		foreach (int item in list)
		{
			if (pendingDrops.TryGetValue(item, out var value2))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP CLEANUP] ClientID=" + item + " Drops=" + value2.Items.Count + " No apareció una muerte dentro de " + 2f.ToString("0.00") + "s."));
			}
			pendingDrops.Remove(item);
		}
	}

	private string FormatVector3(Vector3 position)
	{
		return "(" + position.x.ToString("0.00") + ", " + position.y.ToString("0.00") + ", " + position.z.ToString("0.00") + ")";
	}

	private void OnDestroy()
	{
		try
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			pendingDrops.Clear();
			protectedDeathChests.Clear();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Error durante cleanup: " + ex));
		}
	}
}