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 BepInEx.Configuration;
using BepInEx.Logging;
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", "2.0.0")]
public class DeathChestPlugin : BaseUnityPlugin
{
private class DroppedItem
{
public int ItemId;
public int Amount;
public int ObjectId;
public GameObject Object;
public DroppedItem(int itemId, int amount, int objectId, GameObject droppedObject)
{
Object = droppedObject;
ItemId = itemId;
Amount = amount;
ObjectId = objectId;
}
}
private class DropBatch
{
public ItemManager Manager;
public int ClientId;
public float FirstDropTime;
public float LastDropTime;
public readonly List<DroppedItem> Items = new List<DroppedItem>();
public DropBatch(int clientId, float time, ItemManager manager)
{
Manager = manager;
ClientId = clientId;
FirstDropTime = time;
LastDropTime = time;
}
}
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 = "2.0.0";
private const float DeathTimeout = 2f;
private const float DropBatchWindow = 0.05f;
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 bool modActive;
private int sessionSceneHandle = -1;
private ItemManager sessionItemManager;
private ConfigEntry<bool> instantRespawn;
private DeathChestPacketHooks packetHooks;
private readonly HashSet<int> queuedRespawns = new HashSet<int>();
private readonly Dictionary<int, DropBatch> pendingDrops = new Dictionary<int, DropBatch>();
private readonly Queue<ProtectedChest> protectedDeathChests = new Queue<ProtectedChest>();
private void Awake()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
instantRespawn = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "InstantRespawn", false, "Automatically revive after death for testing. F7 toggles this setting.");
packetHooks = new DeathChestPacketHooks(HandleDropPacket, HandleDeathPacket);
harmony = new Harmony("com.robertomontanas.muck.deathchest");
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.sceneUnloaded += OnSceneUnloaded;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Death Chest v2.0.0 - host only, packet tracking, expandable chests, test respawn");
OnSceneLoaded(SceneManager.GetActiveScene(), (LoadSceneMode)0);
}
private void InstallPatches()
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected O, but got Unknown
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Expected O, but got Unknown
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Expected O, but got Unknown
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Expected O, but got Unknown
//IL_028a: Unknown result type (might be due to invalid IL or missing references)
//IL_0298: Expected O, but got Unknown
//IL_032c: Unknown result type (might be due to invalid IL or missing references)
//IL_0339: Expected O, but got Unknown
//IL_0398: Unknown result type (might be due to invalid IL or missing references)
//IL_03a5: Expected O, but got Unknown
//IL_0405: Unknown result type (might be due to invalid IL or missing references)
//IL_0413: Expected O, but got Unknown
harmony.Patch((MethodBase)AccessTools.Method(typeof(Server), "InitializeServerPackets", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(DeathChestPlugin), "ServerPacketsInitializedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)AccessTools.Method(typeof(GameManager), "CheckIfGameOver", (Type[])null, (Type[])null), new HarmonyMethod(typeof(DeathChestPlugin), "CheckGameOverPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
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).");
throw new MissingMethodException("ItemManager.DropItem");
}
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(DeathChestPlugin), "ItemManagerDropItemPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
((BaseUnityPlugin)this).Logger.LogInfo((object)"Hook instalado: ItemManager.DropItem(...)");
harmony.Patch((MethodBase)AccessTools.Method(typeof(ServerSend), "DropItem", new Type[4]
{
typeof(int),
typeof(int),
typeof(int),
typeof(int)
}, (Type[])null), new HarmonyMethod(typeof(DeathChestPlugin), "ServerDropBroadcastPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)AccessTools.Method(typeof(ServerSend), "PlayerDied", new Type[4]
{
typeof(int),
typeof(Vector3),
typeof(Vector3),
typeof(int)
}, (Type[])null), new HarmonyMethod(typeof(DeathChestPlugin), "ServerDeathBroadcastPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
MethodInfo methodInfo2 = AccessTools.Method(typeof(Hitable), "Damage", new Type[4]
{
typeof(int),
typeof(int),
typeof(int),
typeof(Vector3)
}, (Type[])null);
if (methodInfo2 == null)
{
((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ Hitable.Damage(int, int, int, Vector3).");
}
else
{
harmony.Patch((MethodBase)methodInfo2, 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 methodInfo3 = AccessTools.Method(typeof(ChestManager), "UpdateChest", new Type[4]
{
typeof(int),
typeof(int),
typeof(int),
typeof(int)
}, (Type[])null);
if (methodInfo3 == null)
{
((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ ChestManager.UpdateChest(int, int, int, int).");
}
else
{
harmony.Patch((MethodBase)methodInfo3, (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 methodInfo4 = AccessTools.Method(typeof(MobServerEnemy), "FindNextPosition", Type.EmptyTypes, (Type[])null);
if (methodInfo4 == null)
{
((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ MobServerEnemy.FindNextPosition().");
}
else
{
harmony.Patch((MethodBase)methodInfo4, (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 methodInfo5 = AccessTools.Method(typeof(MobServerEnemy), "TryAttack", Type.EmptyTypes, (Type[])null);
if (methodInfo5 == null)
{
((BaseUnityPlugin)this).Logger.LogError((object)"NO SE ENCONTRÓ MobServerEnemy.TryAttack().");
return;
}
harmony.Patch((MethodBase)methodInfo5, 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 (!Instance.modActive)
{
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 || !Instance.modActive)
{
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_00dc: Unknown result type (might be due to invalid IL or missing references)
if (!IsProtectedDeathChest(chestId))
{
return;
}
ChestManager chestManager = GetChestManager();
if (chestManager == 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_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Instance == (Object)null || !Instance.modActive || (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 (!Instance.modActive)
{
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 ItemManagerDropItemPostfix(ItemManager __instance, int fromClient, int itemId, int amount, int objectID)
{
if ((Object)(object)Instance == (Object)null || !Instance.modActive || !LocalClient.serverOwner)
{
return;
}
try
{
Instance.RegisterDrop(__instance, 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(ItemManager manager, int clientId, int itemId, int amount, int objectId)
{
if (!modActive || manager == null || manager.list == null || amount <= 0 || !manager.list.TryGetValue(objectId, out var droppedObject) || (Object)(object)droppedObject == (Object)null)
{
return;
}
if (sessionItemManager != manager)
{
pendingDrops.Clear();
sessionItemManager = manager;
}
if (pendingDrops.TryGetValue(clientId, out var value) && value.Items.Exists((DroppedItem droppedItem) => droppedItem.ObjectId == objectId && (Object)(object)droppedItem.Object == (Object)(object)droppedObject))
{
return;
}
float realtimeSinceStartup = Time.realtimeSinceStartup;
if (pendingDrops.TryGetValue(clientId, out var value2))
{
float num = realtimeSinceStartup - value2.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);
value2 = null;
}
else
{
value2.LastDropTime = realtimeSinceStartup;
}
}
if (!pendingDrops.TryGetValue(clientId, out var value3))
{
value3 = new DropBatch(clientId, realtimeSinceStartup, manager);
pendingDrops.Add(clientId, value3);
}
DroppedItem item = new DroppedItem(itemId, amount, objectId, droppedObject);
if (!value3.Items.Exists((DroppedItem droppedItem) => droppedItem.ObjectId == objectId))
{
value3.Items.Add(item);
value3.LastDropTime = realtimeSinceStartup;
string itemName = GetItemName(itemId);
float num2 = realtimeSinceStartup - value3.FirstDropTime;
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP] ClientID=" + clientId + " ItemID=" + itemId + " ItemName=\"" + itemName + "\" Amount=" + amount + " ObjectID=" + objectId + " BatchDrops=" + value3.Items.Count + " SinceFirstDrop=" + (num2 * 1000f).ToString("0.000") + "ms"));
}
}
private static void ServerDropBroadcastPrefix(int fromClient, int itemId, int amount, int objectID)
{
if ((Object)(object)Instance == (Object)null || !Instance.modActive || !LocalClient.serverOwner)
{
return;
}
try
{
Instance.RegisterDrop(Instance.GetItemManager(), fromClient, itemId, amount, objectID);
}
catch (Exception ex)
{
((BaseUnityPlugin)Instance).Logger.LogError((object)("[DROP BROADCAST] " + ex));
}
}
private static void ServerDeathBroadcastPrefix(int deadPlayerId, ref Vector3 gravePos)
{
if ((Object)(object)Instance == (Object)null || !Instance.modActive || !LocalClient.serverOwner)
{
return;
}
try
{
Instance.ProcessDeath(deadPlayerId, ref gravePos);
}
catch (Exception ex)
{
((BaseUnityPlugin)Instance).Logger.LogError((object)("[DEATH] " + ex));
}
}
private void ProcessDeath(int clientId, ref Vector3 gravePosition)
{
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_029e: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
if (!pendingDrops.TryGetValue(clientId, out var batch))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] Client=" + clientId + " No tracked drops. Host=" + LocalClient.serverOwner));
return;
}
pendingDrops.Remove(clientId);
if (Time.realtimeSinceStartup - batch.LastDropTime > 2f)
{
return;
}
batch.Items.RemoveAll((DroppedItem item) => batch.Manager == null || batch.Manager.list == null || !batch.Manager.list.TryGetValue(item.ObjectId, out var value2) || (Object)(object)value2 == (Object)null || (Object)(object)value2 != (Object)(object)item.Object);
if (batch.Items.Count == 0)
{
return;
}
int num = FindChestItemId();
if (num < 0)
{
return;
}
Vector3 val = gravePosition;
List<int> list = new List<int>();
int chestCount = GetChestCount(batch.Items.Count);
float num2 = 3f;
RaycastHit val3 = default(RaycastHit);
for (int num3 = 0; num3 < chestCount; num3++)
{
Vector3 val2 = val + Vector3.right * ((float)num3 * num2);
GameManager gameManager = GetGameManager();
if (num3 > 0 && (Object)(object)gameManager != (Object)null && Physics.Raycast(val2 + Vector3.up * 10f, Vector3.down, ref val3, 30f, LayerMask.op_Implicit(gameManager.whatIsGround)))
{
val2.y = ((RaycastHit)(ref val3)).point.y;
}
int num4 = CreateChest(clientId, num, val2 + Vector3.up);
if (num4 < 0)
{
break;
}
ResourceManager resourceManager = GetResourceManager();
if (resourceManager == null || !resourceManager.list.TryGetValue(num4, out var value) || (Object)(object)value == (Object)null)
{
break;
}
Bounds chestBounds = GetChestBounds(value);
if (num3 == 0)
{
num2 = Mathf.Max(3f, ((Bounds)(ref chestBounds)).size.x + 0.5f);
}
CalculatePlacement(val2, value.transform.position, chestBounds, out var finalChestPosition, out var gravePosition2);
value.transform.position = finalChestPosition;
ServerSend.SendBuild(clientId, num, num4, finalChestPosition, 0);
list.Add(num4);
if (num3 == 0)
{
gravePosition = gravePosition2;
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DEATH] Client=" + clientId + " Drops=" + batch.Items.Count + " Chests=" + list.Count + "/" + chestCount + " Grave=" + FormatVector3(gravePosition)));
if (list.Count > 0)
{
((MonoBehaviour)this).StartCoroutine(FillChestsNextFrame(clientId, list, batch));
}
}
private static int GetChestCount(int itemCount)
{
if (itemCount > 0)
{
return (itemCount - 1) / 21 + 1;
}
return 0;
}
private static Bounds GetChestBounds(GameObject chestObject)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
Bounds bounds = default(Bounds);
((Bounds)(ref bounds))..ctor(chestObject.transform.position, Vector3.one);
bool flag = false;
Renderer[] componentsInChildren = chestObject.GetComponentsInChildren<Renderer>();
foreach (Renderer val in componentsInChildren)
{
if (val.enabled && !(val is ParticleSystemRenderer))
{
if (!flag)
{
bounds = val.bounds;
flag = true;
}
else
{
((Bounds)(ref bounds)).Encapsulate(val.bounds);
}
}
}
return bounds;
}
private static void CalculatePlacement(Vector3 groundPosition, Vector3 chestPosition, Bounds bounds, out Vector3 finalChestPosition, out Vector3 gravePosition)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
float num = groundPosition.y + 0.05f - ((Bounds)(ref bounds)).min.y;
finalChestPosition = chestPosition + Vector3.up * num;
gravePosition = new Vector3(groundPosition.x, ((Bounds)(ref bounds)).max.y + num + 0.05f, groundPosition.z);
}
private int CreateChest(int clientId, int chestItemId, Vector3 position)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
try
{
ResourceManager resourceManager = GetResourceManager();
if (resourceManager == null)
{
((BaseUnityPlugin)this).Logger.LogError((object)"[CHEST] No se pudo recuperar ResourceManager.");
return -1;
}
BuildManager buildManager = GetBuildManager();
if (buildManager == 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, List<int> chestIds, DropBatch batch)
{
yield return null;
if (!modActive || !LocalClient.serverOwner)
{
yield break;
}
ChestManager chestManager = GetChestManager();
if (chestManager == null || chestManager.chests == null)
{
yield break;
}
List<DroppedItem> list = new List<DroppedItem>();
int num = 0;
foreach (int chestId in chestIds)
{
if (!chestManager.chests.TryGetValue(chestId, out var value) || (Object)(object)value == (Object)null || value.cells == null)
{
continue;
}
int num2 = 0;
while (num2 < Math.Min(21, value.cells.Length) && num < batch.Items.Count)
{
DroppedItem droppedItem = batch.Items[num++];
if (batch.Manager != null && batch.Manager.list != null && batch.Manager.list.TryGetValue(droppedItem.ObjectId, out var value2) && !((Object)(object)value2 == (Object)null) && !((Object)(object)value2 != (Object)(object)droppedItem.Object))
{
try
{
chestManager.UpdateChest(chestId, num2, droppedItem.ItemId, droppedItem.Amount);
ServerSend.UpdateChest(clientId, chestId, num2, droppedItem.ItemId, droppedItem.Amount);
list.Add(droppedItem);
num2++;
}
catch (Exception ex)
{
value.cells[num2] = null;
((BaseUnityPlugin)this).Logger.LogError((object)("[CHEST CONTENT] Item left on ground: " + ex));
break;
}
}
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("[CHEST CONTENT] Chests=" + chestIds.Count + " Stored=" + list.Count + " Unstored=" + (batch.Items.Count - list.Count)));
yield return ((MonoBehaviour)this).StartCoroutine(RemoveOriginalDropsWithRetries(clientId, batch.Manager, list));
}
private IEnumerator RemoveOriginalDropsWithRetries(int clientId, ItemManager itemManager, List<DroppedItem> objectIds)
{
if (!modActive)
{
yield break;
}
if (objectIds == null || objectIds.Count == 0)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"[DROP REMOVE] No hay drops para eliminar.");
yield break;
}
List<DroppedItem> remainingObjectIds = new List<DroppedItem>(objectIds);
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Objetos a eliminar=" + remainingObjectIds.Count));
int totalRemoved = 0;
int totalFailed = 0;
int totalPasses = 3;
for (int pass = 0; pass < totalPasses; pass++)
{
if (remainingObjectIds.Count == 0)
{
break;
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Iniciando pasada " + (pass + 1) + "/" + totalPasses + ". Objetos pendientes=" + remainingObjectIds.Count));
List<DroppedItem> list = new List<DroppedItem>();
foreach (DroppedItem item in remainingObjectIds)
{
int objectId = item.ObjectId;
if (itemManager == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Pasada=" + (pass + 1) + "/" + totalPasses + " ObjectID=" + objectId + " ItemManager no disponible."));
list.Add(item);
}
else if (itemManager.list == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Pasada=" + (pass + 1) + "/" + totalPasses + " ObjectID=" + objectId + " ItemManager.list es null."));
list.Add(item);
}
else if (!itemManager.list.ContainsKey(objectId))
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Pasada=" + (pass + 1) + "/" + totalPasses + " ObjectID=" + objectId + " no existe en ItemManager.list."));
list.Add(item);
}
else
{
if (!itemManager.list.TryGetValue(objectId, out var value) || (Object)(object)value == (Object)null || (Object)(object)value != (Object)(object)item.Object)
{
continue;
}
bool flag = false;
try
{
flag = itemManager.PickupItem(objectId);
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Pasada=" + (pass + 1) + "/" + totalPasses + " ObjectID=" + objectId + " PickupItem lanzó excepción: " + ex.Message));
}
if (flag)
{
try
{
ServerSend.PickupItem(-1, objectId);
}
catch (Exception ex2)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] ObjectID=" + objectId + " eliminado, pero ServerSend.PickupItem falló: " + ex2.Message));
}
totalRemoved++;
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] ObjectID=" + objectId + " eliminado. Pasada=" + (pass + 1) + "/" + totalPasses));
}
else
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[DROP REMOVE] Pasada=" + (pass + 1) + "/" + totalPasses + " ObjectID=" + objectId + " PickupItem devolvió false."));
list.Add(item);
}
}
}
remainingObjectIds = list;
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Pasada " + (pass + 1) + "/" + totalPasses + " finalizada. Eliminados acumulados=" + totalRemoved + " Pendientes=" + remainingObjectIds.Count));
if (remainingObjectIds.Count > 0 && pass < totalPasses - 1)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Esperando " + 100f.ToString("0") + "ms antes de la siguiente pasada."));
yield return (object)new WaitForSecondsRealtime(0.1f);
}
}
int count = remainingObjectIds.Count;
if (count > 0)
{
totalFailed = count;
}
((BaseUnityPlugin)this).Logger.LogInfo((object)"----------------------------------------");
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Resultado para ClientID=" + clientId));
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Objetos originales=" + objectIds.Count));
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Eliminados=" + totalRemoved));
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Pendientes/no eliminados=" + count));
((BaseUnityPlugin)this).Logger.LogInfo((object)("[DROP REMOVE] Fallidos=" + totalFailed));
((BaseUnityPlugin)this).Logger.LogInfo((object)"----------------------------------------");
}
private int FindChestItemId()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Invalid comparison between Unknown and I4
ItemManager itemManager = GetItemManager();
if (itemManager == 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 (itemManager == 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 static bool HasItemManagerData(ItemManager manager)
{
if (manager != null && manager.list != null)
{
return manager.allItems != null;
}
return false;
}
private ItemManager GetItemManager()
{
if (HasItemManagerData(ItemManager.Instance))
{
return ItemManager.Instance;
}
if (HasItemManagerData(sessionItemManager))
{
return sessionItemManager;
}
return FindSceneManager<ItemManager>();
}
private ResourceManager GetResourceManager()
{
if (ResourceManager.Instance != null && ResourceManager.Instance.list != null)
{
return ResourceManager.Instance;
}
return FindSceneManager<ResourceManager>();
}
private BuildManager GetBuildManager()
{
if (BuildManager.Instance == null)
{
return FindSceneManager<BuildManager>();
}
return BuildManager.Instance;
}
private ChestManager GetChestManager()
{
if (ChestManager.Instance != null && ChestManager.Instance.chests != null)
{
return ChestManager.Instance;
}
return FindSceneManager<ChestManager>();
}
private GameManager GetGameManager()
{
if (!((Object)(object)GameManager.instance != (Object)null))
{
return FindSceneManager<GameManager>();
}
return GameManager.instance;
}
private static T FindSceneManager<T>() where T : MonoBehaviour
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
T[] array = Resources.FindObjectsOfTypeAll<T>();
foreach (T val in array)
{
if (!((Object)(object)val != (Object)null))
{
continue;
}
Scene scene = ((Component)(object)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
scene = ((Component)(object)val).gameObject.scene;
if (((Scene)(ref scene)).isLoaded)
{
return val;
}
}
}
return default(T);
}
private void Update()
{
//IL_0079: 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)
if (Input.GetKeyDown((KeyCode)288))
{
instantRespawn.Value = !instantRespawn.Value;
((BaseUnityPlugin)this).Config.Save();
((BaseUnityPlugin)this).Logger.LogInfo((object)("[TEST] Instant respawn=" + instantRespawn.Value));
}
if (modActive && LocalClient.serverOwner)
{
EnsurePacketHooks();
}
if (Input.GetKeyDown((KeyCode)289))
{
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name == "GameAfterLobby")
{
RestartHooks();
}
}
if (!modActive)
{
return;
}
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 static void ServerPacketsInitializedPostfix()
{
if ((Object)(object)Instance != (Object)null && Instance.modActive && LocalClient.serverOwner)
{
Instance.EnsurePacketHooks();
}
}
private void EnsurePacketHooks()
{
if (packetHooks.Bind(Server.PacketHandlers))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"[NETWORK] Bound drop/death handlers for this session.");
}
}
private void HandleDropPacket(int clientId, Packet packet, PacketHandler original)
{
if (!modActive || !LocalClient.serverOwner || packet.UnreadLength() < 8)
{
original.Invoke(clientId, packet);
return;
}
byte[] value = packet.ReadBytes(8, false);
int num = BitConverter.ToInt32(value, 0);
int num2 = BitConverter.ToInt32(value, 4);
ItemManager itemManager = GetItemManager();
Dictionary<int, GameObject> dictionary = ((itemManager != null && itemManager.list != null) ? new Dictionary<int, GameObject>(itemManager.list) : new Dictionary<int, GameObject>());
original.Invoke(clientId, packet);
try
{
ItemManager itemManager2 = GetItemManager();
int num3 = 0;
int num4 = 0;
if (itemManager2 != null && itemManager2.list != null)
{
foreach (KeyValuePair<int, GameObject> item in itemManager2.list)
{
if ((Object)(object)item.Value == (Object)null || (itemManager2 == itemManager && dictionary.TryGetValue(item.Key, out var value2) && (Object)(object)value2 == (Object)(object)item.Value))
{
continue;
}
num4++;
Item component = item.Value.GetComponent<Item>();
if (!((Object)(object)component == (Object)null) && !((Object)(object)component.item == (Object)null))
{
if (component.item.id != num || component.item.amount != num2)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[NETWORK DROP] Metadata mismatch. Requested=" + num + ":" + num2 + " Actual=" + component.item.id + ":" + component.item.amount + " Object=" + item.Key));
}
else
{
RegisterDrop(itemManager2, clientId, num, num2, item.Key);
num3++;
}
}
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("[NETWORK DROP] Client=" + clientId + " Item=" + num + " Amount=" + num2 + " Created=" + num3 + " NewObjects=" + num4 + " Managed=" + (itemManager2 != null) + " NativeAlive=" + ((Object)(object)itemManager2 != (Object)null) + " Before=" + dictionary.Count + " After=" + ((itemManager2 != null && itemManager2.list != null) ? itemManager2.list.Count : (-1))));
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("[NETWORK DROP] " + ex));
}
}
private void HandleDeathPacket(int clientId, Packet packet, PacketHandler original)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Invalid comparison between Unknown and I4
Client value;
bool flag = modActive && LocalClient.serverOwner && instantRespawn.Value && (int)GameManager.gameSettings.gameMode != 1 && (Object)(object)GameManager.instance != (Object)null && !GameManager.instance.boatLeft && Server.clients.TryGetValue(clientId, out value) && value.player != null && !value.player.dead && queuedRespawns.Add(clientId);
try
{
original.Invoke(clientId, packet);
}
catch
{
if (flag)
{
queuedRespawns.Remove(clientId);
}
throw;
}
if (flag)
{
((MonoBehaviour)this).StartCoroutine(RespawnForTesting(clientId));
}
}
private static bool CheckGameOverPrefix()
{
if (!((Object)(object)Instance == (Object)null) && Instance.modActive && LocalClient.serverOwner)
{
return Instance.queuedRespawns.Count == 0;
}
return true;
}
private IEnumerator RespawnForTesting(int clientId)
{
try
{
yield return (object)new WaitForSecondsRealtime(0.2f);
float deadline = Time.realtimeSinceStartup + 3f;
while (modActive && LocalClient.serverOwner && Time.realtimeSinceStartup < deadline)
{
if (!Server.clients.TryGetValue(clientId, out var value) || value.player == null || !value.player.dead)
{
yield break;
}
if (GameManager.players.TryGetValue(clientId, out var value2) && (Object)(object)value2 != (Object)null && (Object)(object)ResourceManager.Instance != (Object)null && ResourceManager.Instance.list.ContainsKey(value2.graveId))
{
int graveId = value2.graveId;
Packet val = new Packet();
try
{
val.Write(clientId);
val.Write(true);
val.Write(graveId);
val.ToArray();
ServerHandle.RevivePlayer(LocalClient.instance.myId, val);
}
finally
{
((IDisposable)val)?.Dispose();
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("[TEST] Revived Client=" + clientId));
yield break;
}
yield return null;
}
((BaseUnityPlugin)this).Logger.LogWarning((object)("[TEST] Revive timed out for Client=" + clientId));
}
finally
{
DeathChestPlugin deathChestPlugin = this;
deathChestPlugin.queuedRespawns.Remove(clientId);
if (deathChestPlugin.modActive && LocalClient.serverOwner && deathChestPlugin.queuedRespawns.Count == 0 && (Object)(object)GameManager.instance != (Object)null)
{
GameManager.instance.CheckIfGameOver();
}
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
if ((int)mode == 0 || !(((Scene)(ref scene)).name != "GameAfterLobby"))
{
StopSession();
sessionSceneHandle = ((Scene)(ref scene)).handle;
if (((Scene)(ref scene)).name == "GameAfterLobby")
{
((MonoBehaviour)this).StartCoroutine(StartSessionNextFrame(((Scene)(ref scene)).handle));
}
}
}
private IEnumerator StartSessionNextFrame(int sceneHandle)
{
yield return null;
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).handle == sceneHandle && ((Scene)(ref activeScene)).isLoaded && ((Scene)(ref activeScene)).name == "GameAfterLobby")
{
RestartHooks();
}
}
private void OnSceneUnloaded(Scene scene)
{
if (((Scene)(ref scene)).handle == sessionSceneHandle)
{
StopSession();
}
}
private void RestartHooks()
{
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
modActive = false;
try
{
harmony.UnpatchSelf();
pendingDrops.Clear();
InstallPatches();
modActive = true;
EnsurePacketHooks();
ItemManager itemManager = GetItemManager();
((BaseUnityPlugin)this).Logger.LogInfo((object)("[MANAGER] ItemManager Managed=" + (itemManager != null) + " NativeAlive=" + ((Object)(object)itemManager != (Object)null) + " UsableData=" + HasItemManagerData(itemManager)));
ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
string[] obj = new string[5] { "[LIFECYCLE] Hooks reinstalled. Scene=", null, null, null, null };
Scene activeScene = SceneManager.GetActiveScene();
obj[1] = ((Scene)(ref activeScene)).name;
obj[2] = " Host=";
obj[3] = LocalClient.serverOwner.ToString();
obj[4] = " Press F8 to reinstall again.";
logger.LogInfo((object)string.Concat(obj));
}
catch (Exception ex)
{
harmony.UnpatchSelf();
((BaseUnityPlugin)this).Logger.LogError((object)("[LIFECYCLE] Hook restart failed: " + ex));
}
}
private void StopSession()
{
modActive = false;
((MonoBehaviour)this).StopAllCoroutines();
queuedRespawns.Clear();
packetHooks?.Detach();
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
pendingDrops.Clear();
protectedDeathChests.Clear();
sessionItemManager = null;
sessionSceneHandle = -1;
((BaseUnityPlugin)this).Logger.LogInfo((object)"[LIFECYCLE] Session stopped; hooks removed.");
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
SceneManager.sceneUnloaded -= OnSceneUnloaded;
StopSession();
if (Instance == this)
{
Instance = null;
}
}
}
internal sealed class DeathChestPacketHooks
{
private readonly Action<int, Packet, PacketHandler> onDrop;
private readonly Action<int, Packet, PacketHandler> onDeath;
private Dictionary<int, PacketHandler> table;
private PacketHandler oldDrop;
private PacketHandler oldDeath;
private PacketHandler dropWrapper;
private PacketHandler deathWrapper;
internal DeathChestPacketHooks(Action<int, Packet, PacketHandler> onDrop, Action<int, Packet, PacketHandler> onDeath)
{
this.onDrop = onDrop;
this.onDeath = onDeath;
}
internal bool Bind(Dictionary<int, PacketHandler> current)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Expected O, but got Unknown
if (current == null)
{
return false;
}
if (table != current)
{
Detach();
table = current;
}
bool result = false;
if (table.TryGetValue(10, out var value) && (Delegate?)(object)value != (Delegate?)(object)dropWrapper)
{
oldDrop = value;
PacketHandler upstream = value;
dropWrapper = (PacketHandler)delegate(int client, Packet packet)
{
onDrop(client, packet, upstream);
};
table[10] = dropWrapper;
result = true;
}
if (table.TryGetValue(27, out var value2) && (Delegate?)(object)value2 != (Delegate?)(object)deathWrapper)
{
oldDeath = value2;
PacketHandler upstream2 = value2;
deathWrapper = (PacketHandler)delegate(int client, Packet packet)
{
onDeath(client, packet, upstream2);
};
table[27] = deathWrapper;
result = true;
}
return result;
}
internal void Detach()
{
if (table != null)
{
if (table.TryGetValue(10, out var value) && (Delegate?)(object)value == (Delegate?)(object)dropWrapper)
{
table[10] = oldDrop;
}
if (table.TryGetValue(27, out var value2) && (Delegate?)(object)value2 == (Delegate?)(object)deathWrapper)
{
table[27] = oldDeath;
}
}
table = null;
oldDrop = (oldDeath = (dropWrapper = (deathWrapper = null)));
}
}