Decompiled source of BetterCorpses v1.2.4

BepInEx\plugins\BetterCorpses\BetterCorpses.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet;
using FishNet.Managing.Timing;
using FishNet.Object;
using FishNet.Object.Delegating;
using FishNet.Object.Synchronizing;
using FishNet.Object.Synchronizing.Internal;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterCorpses")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("更好的尸体:玩家尸体可卖钱/赌博/抽奖,复活强制等待 + 拍活吃尸体")]
[assembly: AssemblyFileVersion("1.2.4.0")]
[assembly: AssemblyInformationalVersion("1.2.4")]
[assembly: AssemblyProduct("BetterCorpses")]
[assembly: AssemblyTitle("BetterCorpses")]
[assembly: AssemblyVersion("1.2.4.0")]
namespace BetterCorpses;

public static class Config
{
	public static ConfigEntry<bool> Master;

	public static ConfigEntry<bool> RespawnTime;

	public static ConfigEntry<bool> CorpseDrop;

	public static ConfigEntry<bool> Sell;

	public static ConfigEntry<bool> Gamble;

	public static ConfigEntry<bool> Lottery;

	public static ConfigEntry<bool> Cannibal;

	public static ConfigEntry<int> CannibalChance;

	public static ConfigEntry<float> ForcedWaitSeconds;

	public static ConfigEntry<float> GiveUpHoldSeconds;

	public static ConfigEntry<int> PriceMin;

	public static ConfigEntry<int> PriceMax;

	public static bool RespawnOn
	{
		get
		{
			if (Master.Value)
			{
				return RespawnTime.Value;
			}
			return false;
		}
	}

	public static bool EconomyOn
	{
		get
		{
			if (Master.Value)
			{
				return CorpseDrop.Value;
			}
			return false;
		}
	}

	public static bool SellOn
	{
		get
		{
			if (EconomyOn)
			{
				return Sell.Value;
			}
			return false;
		}
	}

	public static bool GambleOn
	{
		get
		{
			if (EconomyOn)
			{
				return Gamble.Value;
			}
			return false;
		}
	}

	public static bool LotteryOn
	{
		get
		{
			if (EconomyOn)
			{
				return Lottery.Value;
			}
			return false;
		}
	}

	public static bool CannibalOn
	{
		get
		{
			if (Master.Value)
			{
				return Cannibal.Value;
			}
			return false;
		}
	}

	public static void Init(BaseUnityPlugin plugin)
	{
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Expected O, but got Unknown
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Expected O, but got Unknown
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Expected O, but got Unknown
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Expected O, but got Unknown
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Expected O, but got Unknown
		Master = plugin.Config.Bind<bool>("General", "Master", true, Loc.Get("cfg.Master"));
		RespawnTime = plugin.Config.Bind<bool>("General", "RespawnTime", true, Loc.Get("cfg.RespawnTime"));
		CorpseDrop = plugin.Config.Bind<bool>("General", "CorpseDrop", true, Loc.Get("cfg.CorpseDrop"));
		Sell = plugin.Config.Bind<bool>("General", "Sell", true, Loc.Get("cfg.Sell"));
		Gamble = plugin.Config.Bind<bool>("General", "Gamble", true, Loc.Get("cfg.Gamble"));
		Lottery = plugin.Config.Bind<bool>("General", "Lottery", true, Loc.Get("cfg.Lottery"));
		Cannibal = plugin.Config.Bind<bool>("General", "Cannibal", true, Loc.Get("cfg.Cannibal"));
		CannibalChance = plugin.Config.Bind<int>("General", "CannibalChance", 50, new ConfigDescription(Loc.Get("cfg.CannibalChance"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		ForcedWaitSeconds = plugin.Config.Bind<float>("Respawn", "ForcedWaitSeconds", 5f, new ConfigDescription(Loc.Get("cfg.ForcedWaitSeconds"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
		GiveUpHoldSeconds = plugin.Config.Bind<float>("Respawn", "GiveUpHoldSeconds", 1f, new ConfigDescription(Loc.Get("cfg.GiveUpHoldSeconds"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
		PriceMin = plugin.Config.Bind<int>("Economy", "PriceMin", -50, new ConfigDescription(Loc.Get("cfg.PriceMin"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10000, 10000), Array.Empty<object>()));
		PriceMax = plugin.Config.Bind<int>("Economy", "PriceMax", 50, new ConfigDescription(Loc.Get("cfg.PriceMax"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10000, 10000), Array.Empty<object>()));
	}
}
internal static class AutoRespawn
{
	private class Pending
	{
		public Player Player;

		public float FireTime;

		public Vector3 Pos;

		public Quaternion Rot;
	}

	private const float DelaySeconds = 1f;

	private static readonly List<Pending> _pending = new List<Pending>();

	public static void Schedule(Player player, Vector3 pos, Quaternion rot)
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)player == (Object)null || ((NetworkBehaviour)player).IsDeinitializing || (Object)(object)player.Vitals == (Object)null)
			{
				return;
			}
			float num = Time.time + 1f;
			if (Config.RespawnOn)
			{
				float serverDeathTime = DeathTimer.GetServerDeathTime(player);
				if (serverDeathTime >= 0f)
				{
					num = Mathf.Max(num, serverDeathTime + Config.ForcedWaitSeconds.Value);
				}
			}
			_pending.Add(new Pending
			{
				Player = player,
				FireTime = num,
				Pos = pos,
				Rot = rot
			});
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("AutoRespawn.Schedule: " + ex.Message);
		}
	}

	public static void Tick()
	{
		try
		{
			if (_pending.Count == 0)
			{
				return;
			}
			for (int num = _pending.Count - 1; num >= 0; num--)
			{
				Pending pending = _pending[num];
				if (!(Time.time < pending.FireTime))
				{
					_pending.RemoveAt(num);
					Fire(pending);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("AutoRespawn.Tick: " + ex.Message);
		}
	}

	private static void Fire(Pending p)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Player player = p.Player;
			if (!((Object)(object)player == (Object)null) && !((NetworkBehaviour)player).IsDeinitializing && !((Object)(object)player.Vitals == (Object)null) && player.Vitals.Health <= 0 && !((Object)(object)Server.Instance == (Object)null) && ((NetworkBehaviour)Server.Instance).IsServerInitialized && !DeathTimer.ServerInWait(player))
			{
				Server.Instance.RespawnPlayer(player, p.Pos, p.Rot);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("AutoRespawn.Fire: " + ex.Message);
		}
	}
}
internal static class CorpseCannibal
{
	private const int ReviverHealAmount = 12;

	public static void TryCannibalize(Player revived, DeadPlayer corpse)
	{
		try
		{
			if (!Config.CannibalOn || (Object)(object)revived == (Object)null || (Object)(object)corpse == (Object)null || (Object)(object)revived.Vitals == (Object)null || revived.Vitals.Health <= 0)
			{
				return;
			}
			Player val = ((Item)corpse).Holder ?? ((Item)corpse).LastHolder;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.Vitals == (Object)null) && !((Object)(object)revived == (Object)(object)val) && Random.Range(0, 100) < Config.CannibalChance.Value)
			{
				int num = HalfOfVanillaRevive(revived);
				revived.Vitals._syncedHealth.Value = Mathf.Clamp(num, 0, 100);
				val.Vitals.Heal(12);
				CannibalFx component = ((Component)val).GetComponent<CannibalFx>();
				if ((Object)(object)component != (Object)null)
				{
					component.PlayEatEffects();
				}
				Plugin.LogInfo("[BetterCorpses] Cannibalism: " + val.SteamName + " ate " + revived.SteamName + "'s corpse (revived at " + num + " HP, reviver healed " + 12 + ")");
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("CorpseCannibal: " + ex.Message);
		}
	}

	private static int HalfOfVanillaRevive(Player revived)
	{
		try
		{
			if (AccessTools.Field(typeof(PlayerVitals), "_healthOnRes").GetValue(revived.Vitals) is int num)
			{
				return Mathf.FloorToInt((float)num * 0.5f);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("HalfOfVanillaRevive: " + ex.Message);
		}
		return 12;
	}
}
internal static class DeathTimer
{
	private static float _localDeathTime = -1f;

	private static readonly Dictionary<Player, float> _serverDeath = new Dictionary<Player, float>();

	public static bool LocalInWait
	{
		get
		{
			if (_localDeathTime < 0f)
			{
				return false;
			}
			return Time.time - _localDeathTime < Config.ForcedWaitSeconds.Value;
		}
	}

	public static float LocalRemaining
	{
		get
		{
			if (_localDeathTime < 0f)
			{
				return 0f;
			}
			return Mathf.Max(0f, Config.ForcedWaitSeconds.Value - (Time.time - _localDeathTime));
		}
	}

	internal static float NetworkTime()
	{
		try
		{
			if ((Object)(object)InstanceFinder.TimeManager != (Object)null)
			{
				return (float)InstanceFinder.TimeManager.TicksToTime((TickType)0);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("DeathTimer.NetworkTime: " + ex.Message);
		}
		return Time.time;
	}

	public static void RecordLocalDeath()
	{
		_localDeathTime = Time.time;
	}

	public static void ClearLocal()
	{
		_localDeathTime = -1f;
	}

	public static void RecordServerDeath(Player p)
	{
		if (!((Object)(object)p == (Object)null))
		{
			_serverDeath[p] = Time.time;
		}
	}

	public static void ClearServer(Player p)
	{
		if (!((Object)(object)p == (Object)null))
		{
			_serverDeath.Remove(p);
		}
	}

	public static bool ServerInWait(Player p)
	{
		if ((Object)(object)p == (Object)null)
		{
			return false;
		}
		if (_serverDeath.TryGetValue(p, out var value))
		{
			return Time.time - value < Config.ForcedWaitSeconds.Value;
		}
		return false;
	}

	public static float GetServerDeathTime(Player p)
	{
		if ((Object)(object)p == (Object)null)
		{
			return -1f;
		}
		if (!_serverDeath.TryGetValue(p, out var value))
		{
			return -1f;
		}
		return value;
	}

	internal static float GetCorpseDeathTime(DeadPlayer corpse)
	{
		try
		{
			if ((Object)(object)corpse == (Object)null)
			{
				return -1f;
			}
			Player player = corpse.Player;
			if ((Object)(object)player != (Object)null)
			{
				CannibalFx component = ((Component)player).GetComponent<CannibalFx>();
				if ((Object)(object)component != (Object)null && component.DeathTime >= 0f)
				{
					return component.DeathTime;
				}
			}
			CorpseEconomy component2 = ((Component)corpse).GetComponent<CorpseEconomy>();
			if ((Object)(object)component2 != (Object)null)
			{
				return component2.DeathTime;
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("GetCorpseDeathTime: " + ex.Message);
		}
		return -1f;
	}

	public static bool CorpseInWait(DeadPlayer corpse)
	{
		float corpseDeathTime = GetCorpseDeathTime(corpse);
		if (corpseDeathTime < 0f)
		{
			return false;
		}
		return NetworkTime() - corpseDeathTime < Config.ForcedWaitSeconds.Value;
	}

	public static float CorpseRemaining(DeadPlayer corpse)
	{
		float corpseDeathTime = GetCorpseDeathTime(corpse);
		if (corpseDeathTime < 0f)
		{
			return 0f;
		}
		return Mathf.Max(0f, Config.ForcedWaitSeconds.Value - (NetworkTime() - corpseDeathTime));
	}
}
public static class Loc
{
	public enum Lang
	{
		Chinese,
		English
	}

	private static Dictionary<string, string> _zh;

	private static Dictionary<string, string> _en;

	private static bool _loaded;

	public static Lang Current { get; private set; }

	public static void Init()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		SystemLanguage systemLanguage = Application.systemLanguage;
		if (systemLanguage - 40 <= 1)
		{
			Current = Lang.Chinese;
		}
		else
		{
			Current = Lang.English;
		}
	}

	private static string FileName(Lang lang)
	{
		if (lang != Lang.Chinese)
		{
			return "en-US.json";
		}
		return "zh-CN.json";
	}

	private static void EnsureLoaded()
	{
		if (_loaded)
		{
			return;
		}
		_loaded = true;
		try
		{
			_zh = LoadTable(Lang.Chinese);
		}
		catch (Exception ex)
		{
			if (Plugin.Log != null)
			{
				Plugin.Log.LogError((object)("zh-CN 加载失败: " + ex.Message));
			}
		}
		try
		{
			_en = LoadTable(Lang.English);
		}
		catch (Exception ex2)
		{
			if (Plugin.Log != null)
			{
				Plugin.Log.LogError((object)("en-US 加载失败: " + ex2.Message));
			}
		}
		if (_zh == null)
		{
			_zh = new Dictionary<string, string>();
		}
		if (_en == null)
		{
			_en = new Dictionary<string, string>();
		}
	}

	private static Dictionary<string, string> LoadTable(Lang lang)
	{
		string text = FileName(lang);
		string embeddedText = GetEmbeddedText(text);
		if (embeddedText == null)
		{
			if (Plugin.Log != null)
			{
				Plugin.Log.LogWarning((object)("未找到内嵌本地化资源: " + text));
			}
			return null;
		}
		try
		{
			return JsonConvert.DeserializeObject<Dictionary<string, string>>(embeddedText);
		}
		catch (Exception ex)
		{
			if (Plugin.Log != null)
			{
				Plugin.Log.LogError((object)("JSON 解析失败: " + text + " -> " + ex.Message));
			}
			return null;
		}
	}

	private static string GetEmbeddedText(string fileName)
	{
		Assembly executingAssembly = Assembly.GetExecutingAssembly();
		string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
		foreach (string text in manifestResourceNames)
		{
			if (!text.EndsWith("." + fileName, StringComparison.OrdinalIgnoreCase))
			{
				continue;
			}
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				return null;
			}
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd();
		}
		return null;
	}

	public static string Get(string key)
	{
		EnsureLoaded();
		Dictionary<string, string> dictionary = ((Current == Lang.Chinese) ? _zh : _en);
		if (dictionary != null && dictionary.TryGetValue(key, out var value) && value != null)
		{
			return value;
		}
		Dictionary<string, string> dictionary2 = ((Current == Lang.Chinese) ? _en : _zh);
		if (dictionary2 != null && dictionary2.TryGetValue(key, out var value2) && value2 != null)
		{
			return value2;
		}
		return "[" + key + "]";
	}

	public static string Get(string key, params object[] args)
	{
		try
		{
			return string.Format(Get(key), args);
		}
		catch (Exception)
		{
			return Get(key);
		}
	}
}
public class CannibalFx : NetworkBehaviour
{
	public readonly SyncVar<float> _deathTime = new SyncVar<float>(-1f, default(SyncTypeSettings));

	private float _pendingDeathTime = -1f;

	private bool _hasPendingDeathTime;

	private bool _nwEarlyExcuted;

	private bool _nwLateExcuted;

	public float DeathTime => _deathTime.Value;

	public virtual void Awake()
	{
		((NetworkBehaviour)this).NetworkInitialize___Early();
		((NetworkBehaviour)this).NetworkInitialize___Late();
	}

	public override void OnStartServer()
	{
		((NetworkBehaviour)this).OnStartServer();
		Plugin.LogInfo("[BetterCorpses] CannibalFx OnStartServer, IsServerInitialized=" + ((NetworkBehaviour)this).IsServerInitialized);
	}

	private void Update()
	{
		try
		{
			if (((NetworkBehaviour)this).IsServerInitialized && _hasPendingDeathTime)
			{
				_deathTime.Value = _pendingDeathTime;
				_hasPendingDeathTime = false;
				Plugin.LogInfo("[BetterCorpses] CannibalFx._deathTime flushed on server: " + _pendingDeathTime.ToString("0.0"));
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("CannibalFx.Update: " + ex.Message);
		}
	}

	public void SetDeathTime(float t)
	{
		try
		{
			if (((NetworkBehaviour)this).IsServerInitialized)
			{
				_deathTime.Value = t;
				Plugin.LogInfo("[BetterCorpses] CannibalFx.SetDeathTime direct: " + t.ToString("0.0") + ", init=" + ((NetworkBehaviour)this).IsServerInitialized);
			}
			else
			{
				_pendingDeathTime = t;
				_hasPendingDeathTime = true;
				Plugin.LogInfo("[BetterCorpses] CannibalFx.SetDeathTime stashed: " + t.ToString("0.0") + ", init=" + ((NetworkBehaviour)this).IsServerInitialized);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("CannibalFx.SetDeathTime: " + ex.Message);
		}
	}

	public void PlayEatEffects()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (((NetworkBehaviour)this).IsServerInitialized)
			{
				Channel val = (Channel)0;
				PooledWriter val2 = WriterPool.Retrieve();
				((NetworkBehaviour)this).SendObserversRpc(0u, val2, val, (DataOrderType)0, false, false, false);
				val2.Store();
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("CannibalFx.PlayEatEffects: " + ex.Message);
		}
	}

	private void RpcLogic___PlayEatEffects()
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Player component = ((Component)this).GetComponent<Player>();
			if (!((Object)(object)component == (Object)null))
			{
				AudioManager.PlayPlayerClip("Swallow", component, true, (AudioDistance)1, 1f, 0.1f);
				ParticleManager.Play("Smoke", component.Transform.position, Vector3.up);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("CannibalFx RpcLogic: " + ex.Message);
		}
	}

	private void RpcReader___PlayEatEffects(PooledReader r, Channel channel)
	{
		if (((NetworkBehaviour)this).IsClientInitialized)
		{
			RpcLogic___PlayEatEffects();
		}
	}

	public override void NetworkInitialize___Early()
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		if (!_nwEarlyExcuted)
		{
			_nwEarlyExcuted = true;
			((NetworkBehaviour)this).NetworkInitialize___Early();
			((SyncBase)_deathTime).InitializeEarly((NetworkBehaviour)(object)this, 0u, false);
			((NetworkBehaviour)this).RegisterObserversRpc(0u, new ClientRpcDelegate(RpcReader___PlayEatEffects));
		}
	}

	public override void NetworkInitialize___Late()
	{
		if (!_nwLateExcuted)
		{
			_nwLateExcuted = true;
			((NetworkBehaviour)this).NetworkInitialize___Late();
			((SyncBase)_deathTime).InitializeLate();
		}
	}

	public override void NetworkInitializeIfDisabled()
	{
		((NetworkBehaviour)this).NetworkInitialize___Early();
		((NetworkBehaviour)this).NetworkInitialize___Late();
	}
}
public class CorpseEconomy : NetworkBehaviour
{
	public readonly SyncVar<int> _price = new SyncVar<int>(0, default(SyncTypeSettings));

	public readonly SyncVar<float> _deathTime = new SyncVar<float>(-1f, default(SyncTypeSettings));

	private float _pendingDeathTime = -1f;

	private bool _hasPendingDeathTime;

	private int _pendingPrice;

	private bool _hasPendingPrice;

	private bool _nwEarlyExcuted;

	private bool _nwLateExcuted;

	public int Price => _price.Value;

	public float DeathTime => _deathTime.Value;

	public virtual void Awake()
	{
		((NetworkBehaviour)this).NetworkInitialize___Early();
		((NetworkBehaviour)this).NetworkInitialize___Late();
	}

	private void Update()
	{
		try
		{
			if (((NetworkBehaviour)this).IsServerInitialized)
			{
				if (_hasPendingDeathTime)
				{
					_deathTime.Value = _pendingDeathTime;
					_hasPendingDeathTime = false;
				}
				if (_hasPendingPrice)
				{
					_price.Value = _pendingPrice;
					_hasPendingPrice = false;
				}
			}
		}
		catch
		{
		}
	}

	public void SetDeathTime(float t)
	{
		try
		{
			if (((NetworkBehaviour)this).IsServerInitialized)
			{
				_deathTime.Value = t;
				return;
			}
			_pendingDeathTime = t;
			_hasPendingDeathTime = true;
		}
		catch
		{
		}
	}

	public void SetPrice(int price)
	{
		try
		{
			if (((NetworkBehaviour)this).IsServerInitialized)
			{
				_price.Value = price;
				return;
			}
			_pendingPrice = price;
			_hasPendingPrice = true;
		}
		catch
		{
		}
	}

	public override void NetworkInitialize___Early()
	{
		if (!_nwEarlyExcuted)
		{
			_nwEarlyExcuted = true;
			((NetworkBehaviour)this).NetworkInitialize___Early();
			((SyncBase)_price).InitializeEarly((NetworkBehaviour)(object)this, 0u, false);
			((SyncBase)_deathTime).InitializeEarly((NetworkBehaviour)(object)this, 1u, false);
		}
	}

	public override void NetworkInitialize___Late()
	{
		if (!_nwLateExcuted)
		{
			_nwLateExcuted = true;
			((NetworkBehaviour)this).NetworkInitialize___Late();
			((SyncBase)_price).InitializeLate();
			((SyncBase)_deathTime).InitializeLate();
		}
	}

	public override void NetworkInitializeIfDisabled()
	{
		((NetworkBehaviour)this).NetworkInitialize___Early();
		((NetworkBehaviour)this).NetworkInitialize___Late();
	}
}
[HarmonyPatch(typeof(PlayerDying), "ServerDie")]
internal static class Patch_ServerDie
{
	private static void Postfix(PlayerDying __instance)
	{
		try
		{
			DeadPlayer deadPlayer = __instance.DeadPlayer;
			if ((Object)(object)deadPlayer == (Object)null)
			{
				return;
			}
			Player player = deadPlayer.Player;
			float deathTime = DeathTimer.NetworkTime();
			if ((Object)(object)player != (Object)null)
			{
				DeathTimer.RecordServerDeath(player);
				CannibalFx component = ((Component)player).GetComponent<CannibalFx>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetDeathTime(deathTime);
				}
			}
			CorpseEconomy component2 = ((Component)deadPlayer).GetComponent<CorpseEconomy>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.SetDeathTime(deathTime);
			}
			Plugin.LogInfo("[BetterCorpses] death recorded owner=" + (((Object)(object)player != (Object)null) ? player.SteamName : "?") + " netTime=" + deathTime.ToString("0.0"));
			if (Config.EconomyOn)
			{
				int num = Random.Range(Config.PriceMin.Value, Config.PriceMax.Value + 1);
				try
				{
					AccessTools.Field(typeof(Item), "_worth").SetValue(deadPlayer, num);
				}
				catch (Exception ex)
				{
					Plugin.LogWarn("Patch_ServerDie _worth: " + ex.Message);
				}
				if ((Object)(object)component2 != (Object)null)
				{
					component2.SetPrice(num);
				}
			}
		}
		catch (Exception ex2)
		{
			Plugin.LogWarn("Patch_ServerDie: " + ex2.Message);
		}
	}
}
[HarmonyPatch(typeof(PlayerDying), "DeathEffects")]
internal static class Patch_DeathEffects
{
	private static void Postfix(PlayerDying __instance)
	{
		try
		{
			if (!((NetworkBehaviour)__instance).Owner.IsLocalClient)
			{
				return;
			}
			DeathTimer.RecordLocalDeath();
			if (!Config.RespawnOn)
			{
				return;
			}
			try
			{
				AccessTools.Field(typeof(PlayerDying), "_totalGiveUpTime").SetValue(__instance, Config.GiveUpHoldSeconds.Value);
			}
			catch (Exception ex)
			{
				Plugin.LogWarn("GiveUpHoldSeconds: " + ex.Message);
			}
		}
		catch (Exception ex2)
		{
			Plugin.LogWarn("Patch_DeathEffects: " + ex2.Message);
		}
	}
}
[HarmonyPatch(typeof(PlayerDying), "ResurrectEffect")]
internal static class Patch_ResurrectEffect
{
	private static void Postfix(PlayerDying __instance)
	{
		try
		{
			DeathTimer.ClearLocal();
			Player component = ((Component)__instance).GetComponent<Player>();
			if ((Object)(object)component != (Object)null)
			{
				DeathTimer.ClearServer(component);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("Patch_ResurrectEffect: " + ex.Message);
		}
	}
}
[HarmonyPatch(typeof(PlayerDying), "LocalResurrect")]
internal static class Patch_LocalResurrect
{
	private static void Prefix(PlayerDying __instance)
	{
		try
		{
			if (Config.Master.Value && (Object)(object)__instance.DeadPlayer == (Object)null)
			{
				AccessTools.Field(typeof(PlayerDying), "_waitingForTpOnRespawn").SetValue(__instance, true);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("Patch_LocalResurrect: " + ex.Message);
		}
	}
}
[HarmonyPatch(typeof(PlayerDying), "MouseClick")]
internal static class Patch_MouseClick
{
	private static bool Prefix()
	{
		if (!Config.RespawnOn)
		{
			return true;
		}
		return !DeathTimer.LocalInWait;
	}
}
[HarmonyPatch(typeof(DeadPlayer), "PrimaryInput")]
internal static class Patch_DeadPlayerPrimaryInput
{
	private static bool Prefix(DeadPlayer __instance)
	{
		if (!Config.RespawnOn)
		{
			return true;
		}
		return !DeathTimer.CorpseInWait(__instance);
	}
}
[HarmonyPatch(typeof(Server), "RpcLogic___ResurrectPlayer___2247010027")]
internal static class Patch_ResurrectPlayer
{
	private static bool Prefix(object[] __args, out bool __state)
	{
		Player val = (Player)((__args != null && __args.Length != 0) ? /*isinst with value type is only supported in some contexts*/: null);
		DeadPlayer val2 = (DeadPlayer)((__args != null && __args.Length > 1) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!((Object)(object)val != (Object)null) || ((NetworkBehaviour)val).IsDeinitializing || !((Object)(object)val.Vitals != (Object)null) || val.Vitals.Health > 0 || !((Object)(object)val2 != (Object)null) || ((NetworkBehaviour)val2).IsDeinitializing)
		{
			__state = false;
			return true;
		}
		if (Config.RespawnOn && (DeathTimer.ServerInWait(val) || DeathTimer.CorpseInWait(val2)))
		{
			__state = false;
			return false;
		}
		__state = true;
		return true;
	}

	private static void Postfix(object[] __args, bool __state)
	{
		if (__state && __args != null && __args.Length >= 2)
		{
			object obj = __args[0];
			Player val = (Player)((obj is Player) ? obj : null);
			object obj2 = __args[1];
			DeadPlayer corpse = (DeadPlayer)((obj2 is DeadPlayer) ? obj2 : null);
			if ((Object)(object)val != (Object)null)
			{
				DeathTimer.ClearServer(val);
			}
			CorpseCannibal.TryCannibalize(val, corpse);
		}
	}
}
[HarmonyPatch(typeof(Server), "RpcLogic___RespawnPlayer___2210451296")]
internal static class Patch_RespawnPlayer
{
	private static bool Prefix(object[] __args, out bool __state)
	{
		__state = true;
		if (!Config.RespawnOn)
		{
			return true;
		}
		Player val = (Player)((__args != null && __args.Length != 0) ? /*isinst with value type is only supported in some contexts*/: null);
		if ((Object)(object)val != (Object)null && DeathTimer.ServerInWait(val))
		{
			__state = false;
			return false;
		}
		return true;
	}

	private static void Postfix(object[] __args, bool __state)
	{
		if (__state && __args != null && __args.Length != 0)
		{
			object obj = __args[0];
			Player val = (Player)((obj is Player) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				DeathTimer.ClearServer(val);
			}
		}
	}
}
[HarmonyPatch(typeof(NPC), "EatItem")]
internal static class Patch_NpcEatCorpse
{
	private static bool Prefix(NPC __instance, NPCQuest quest, byte questIndex, Item item)
	{
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Invalid comparison between Unknown and I4
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		if (!Config.SellOn)
		{
			return true;
		}
		if ((Object)(object)item == (Object)null || (Object)(object)item.DeadPlayer == (Object)null)
		{
			return true;
		}
		if ((Object)(object)quest == (Object)null || (int)quest.Type != 1)
		{
			return true;
		}
		if ((Object)(object)Server.Instance == (Object)null || !((NetworkBehaviour)Server.Instance).IsServerInitialized)
		{
			return true;
		}
		if (item.IsDestroying || ((NetworkBehaviour)item).IsDeinitializing)
		{
			return false;
		}
		try
		{
			Vector3 position = ((Component)item).transform.position;
			Quaternion rotation = ((Component)item).transform.rotation;
			Player player = item.DeadPlayer.Player;
			MoneyManager.SellItem(item);
			byte b = (byte)AccessTools.Field(typeof(NPC), "_id").GetValue(__instance);
			item.DestroyItem((byte)2, b);
			try
			{
				NPCManager.Instance.SendEatEffects(b);
			}
			catch (Exception ex)
			{
				Plugin.LogWarn("SendEatEffects: " + ex.Message);
			}
			try
			{
				AccessTools.Method(typeof(NPC), "OnQuestProgression", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { questIndex });
			}
			catch (Exception ex2)
			{
				Plugin.LogWarn("OnQuestProgression: " + ex2.Message);
			}
			if ((Object)(object)player != (Object)null)
			{
				AutoRespawn.Schedule(player, position, rotation);
			}
		}
		catch (Exception ex3)
		{
			Plugin.LogWarn("Patch_NpcEatCorpse: " + ex3.Message);
		}
		return false;
	}
}
[HarmonyPatch(typeof(CasinoBox), "FixedUpdate")]
internal static class Patch_CasinoBoxCorpses
{
	private static bool Prefix(CasinoBox __instance)
	{
		//IL_0070: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		if (!Config.GambleOn)
		{
			return true;
		}
		if ((Object)(object)Server.Instance == (Object)null || !((NetworkBehaviour)Server.Instance).IsServerInitialized || ((Object)(object)CasinoManager.Instance != (Object)null && CasinoManager.IsBetting))
		{
			return true;
		}
		try
		{
			object? value = AccessTools.Field(typeof(CasinoBox), "_col").GetValue(__instance);
			BoxCollider val = (BoxCollider)((value is BoxCollider) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			Vector3 val2 = ((Component)val).transform.TransformPoint(val.center);
			Vector3 val3 = Vector3.Scale(val.size * 0.5f, ((Component)__instance).transform.localScale);
			Collider[] array = Physics.OverlapBox(val2, val3, ((Component)__instance).transform.rotation, LayerMask.op_Implicit(GameInfo.ItemLayer));
			List<Item> list = new List<Item>();
			Collider[] array2 = array;
			foreach (Collider val4 in array2)
			{
				if (((Component)((Component)val4).transform).CompareTag("Item"))
				{
					Item val5 = ItemManager.Get(val4);
					if ((Object)(object)val5 != (Object)null && !list.Contains(val5) && (!Object.op_Implicit((Object)(object)val5.Creature) || val5.Creature.IsDead))
					{
						list.Add(val5);
					}
				}
			}
			CasinoManager.SetBetItems(list);
			return false;
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("Patch_CasinoBoxCorpses: " + ex.Message);
			return true;
		}
	}
}
[HarmonyPatch(typeof(BetButton), "ToggleAll")]
internal static class Patch_BetButtonToggleAll
{
	internal static bool SuppressModEnable;

	private static bool Prefix(ref bool to)
	{
		try
		{
			if (!Config.GambleOn)
			{
				return true;
			}
			if (to || SuppressModEnable)
			{
				return true;
			}
			CasinoManager instance = CasinoManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			if (instance.TotalWorth != 0)
			{
				to = true;
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("Patch_BetButtonToggleAll: " + ex.Message);
		}
		return true;
	}
}
[HarmonyPatch(typeof(CasinoManager), "get_HasPlacedBet")]
internal static class Patch_HasPlacedBet
{
	private static void Postfix(ref bool __result)
	{
		try
		{
			if (Config.GambleOn)
			{
				CasinoManager instance = CasinoManager.Instance;
				if (!((Object)(object)instance == (Object)null) && instance.TotalWorth != 0)
				{
					__result = true;
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("Patch_HasPlacedBet: " + ex.Message);
		}
	}
}
[HarmonyPatch(typeof(CasinoManager), "RpcLogic___BetResultEffects___2774100791")]
internal static class Patch_BetResultEffects
{
	private static void Prefix()
	{
		Patch_BetButtonToggleAll.SuppressModEnable = true;
	}

	private static void Postfix()
	{
		Patch_BetButtonToggleAll.SuppressModEnable = false;
	}
}
[HarmonyPatch(typeof(SlotMachine), "OnTriggerStay")]
internal static class Patch_SlotMachineCorpses
{
	private static bool Prefix(Collider other)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		if (!Config.LotteryOn)
		{
			return true;
		}
		if ((Object)(object)Server.Instance == (Object)null || !((NetworkBehaviour)Server.Instance).IsServerInitialized || SlotMachine.IsRolling)
		{
			return true;
		}
		try
		{
			Item val = ItemManager.Get(other);
			if ((Object)(object)val == (Object)null || (Object)(object)val.DeadPlayer == (Object)null)
			{
				return true;
			}
			if (Object.op_Implicit((Object)(object)val.Holder))
			{
				return true;
			}
			Player lastHolder = val.LastHolder;
			if ((Object)(object)lastHolder == (Object)null)
			{
				return true;
			}
			Vector3 position = ((Component)val).transform.position;
			Quaternion rotation = ((Component)val).transform.rotation;
			Player player = val.DeadPlayer.Player;
			val.DestroyItem((byte)4, byte.MaxValue);
			SlotMachineManager.RollRandom(lastHolder);
			if ((Object)(object)player != (Object)null)
			{
				AutoRespawn.Schedule(player, position, rotation);
			}
			return false;
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("Patch_SlotMachineCorpses: " + ex.Message);
			return true;
		}
	}
}
[HarmonyPatch(typeof(MoneyManager), "Update")]
internal static class Patch_DriveTick
{
	private static void Postfix()
	{
		Plugin.RuntimeTick();
	}
}
[BepInPlugin("top.yw.bettercorpses", "更好的尸体", "1.2.4")]
public class Plugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	public static bool ComponentsAttached;

	internal static void LogInfo(string msg)
	{
		try
		{
			Log.LogInfo((object)msg);
		}
		catch
		{
		}
	}

	internal static void LogWarn(string msg)
	{
		try
		{
			Log.LogWarning((object)msg);
		}
		catch
		{
		}
	}

	private void Awake()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		Loc.Init();
		Config.Init((BaseUnityPlugin)(object)this);
		Harmony val = new Harmony("top.yw.bettercorpses");
		int num = 0;
		int num2 = 0;
		Type[] types = typeof(Plugin).Assembly.GetTypes();
		foreach (Type type in types)
		{
			if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0)
			{
				try
				{
					new PatchClassProcessor(val, type).Patch();
					num++;
				}
				catch (Exception ex)
				{
					num2++;
					LogWarn("补丁应用失败:" + type.Name + " => " + ex.GetType().Name + ": " + ex.Message);
				}
			}
		}
		LogInfo("[BetterCorpses] Harmony 补丁应用完成(成功 " + num + " 失败 " + num2 + ")");
	}

	private void Update()
	{
		RuntimeTick();
	}

	public static void RuntimeTick()
	{
		try
		{
			EnsureAttached();
		}
		catch
		{
		}
		try
		{
			AutoRespawn.Tick();
		}
		catch
		{
		}
		try
		{
			HudUI.Tick();
		}
		catch
		{
		}
	}

	private static void EnsureAttached()
	{
		if (!ComponentsAttached)
		{
			AttachComponents();
		}
	}

	public static void AttachComponents()
	{
		if (ComponentsAttached)
		{
			return;
		}
		try
		{
			if (!((Object)(object)GameInfo.DeadPlayerPrefab == (Object)null) && !((Object)(object)GameInfo.PlayerPrefab == (Object)null))
			{
				GameObject gameObject = ((Component)GameInfo.DeadPlayerPrefab).gameObject;
				if ((Object)(object)gameObject.GetComponent<CorpseEconomy>() == (Object)null)
				{
					gameObject.AddComponent<CorpseEconomy>();
				}
				GameObject gameObject2 = ((Component)GameInfo.PlayerPrefab).gameObject;
				if ((Object)(object)gameObject2.GetComponent<CannibalFx>() == (Object)null)
				{
					gameObject2.AddComponent<CannibalFx>();
				}
				ComponentsAttached = true;
				LogInfo("[BetterCorpses] CorpseEconomy/CannibalFx 已挂载(DeadPlayerPrefab/PlayerPrefab)");
			}
		}
		catch (Exception ex)
		{
			LogWarn("AttachComponents 失败(稍后重试): " + ex.Message);
		}
	}
}
internal static class HudUI
{
	private static Canvas _canvas;

	private static Text _waitText;

	private static Text _corpseWaitText;

	private static float _refreshTimer;

	private static DeadPlayer _diagCorpse;

	private static void Ensure()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_canvas != (Object)null))
		{
			GameObject val = new GameObject("BetterCorpses_UI");
			Object.DontDestroyOnLoad((Object)val);
			_canvas = val.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 30000;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			val.AddComponent<GraphicRaycaster>();
			_waitText = CreateText(val.transform, new Vector2(0.5f, 0.2f), new Vector2(800f, 80f), 44);
			((Component)_waitText).gameObject.SetActive(false);
			_corpseWaitText = CreateText(val.transform, new Vector2(0.5f, 0.92f), new Vector2(1000f, 90f), 48);
			((Component)_corpseWaitText).gameObject.SetActive(false);
		}
	}

	private static Text CreateText(Transform parent, Vector2 anchor, Vector2 size, int fontSize)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("WrText", new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(parent, false);
		RectTransform component = val.GetComponent<RectTransform>();
		component.anchorMin = anchor;
		component.anchorMax = anchor;
		component.pivot = new Vector2(0.5f, 0.5f);
		component.anchoredPosition = Vector2.zero;
		component.sizeDelta = size;
		Text obj = val.AddComponent<Text>();
		obj.font = UiFonts.Cjk;
		obj.fontSize = fontSize;
		((Graphic)obj).color = Color.white;
		obj.alignment = (TextAnchor)4;
		obj.horizontalOverflow = (HorizontalWrapMode)1;
		obj.verticalOverflow = (VerticalWrapMode)1;
		Outline obj2 = val.AddComponent<Outline>();
		((Shadow)obj2).effectColor = new Color(0f, 0f, 0f, 0.8f);
		((Shadow)obj2).effectDistance = new Vector2(1f, -1f);
		return obj;
	}

	public static void Tick()
	{
		try
		{
			Ensure();
		}
		catch
		{
			return;
		}
		_refreshTimer -= Time.unscaledDeltaTime;
		if (_refreshTimer > 0f)
		{
			return;
		}
		_refreshTimer = 0.25f;
		try
		{
			RefreshWaitText();
		}
		catch
		{
		}
	}

	private static void RefreshWaitText()
	{
		Player localPlayer = Player.LocalPlayer;
		if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.Dying != (Object)null && localPlayer.Dying.IsDead && Config.RespawnOn && DeathTimer.LocalInWait)
		{
			((Component)_waitText).gameObject.SetActive(true);
			_waitText.text = Loc.Get("hud.respawnWait", Mathf.CeilToInt(DeathTimer.LocalRemaining));
			((Component)_corpseWaitText).gameObject.SetActive(false);
			return;
		}
		if (Config.RespawnOn && (Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.Holding != (Object)null)
		{
			Item heldItem = localPlayer.Holding.HeldItem;
			DeadPlayer val = (DeadPlayer)(object)((heldItem is DeadPlayer) ? heldItem : null);
			if ((Object)(object)val != (Object)null)
			{
				if (DeathTimer.CorpseInWait(val))
				{
					((Component)_corpseWaitText).gameObject.SetActive(true);
					_corpseWaitText.text = Loc.Get("hud.corpseWait", Mathf.CeilToInt(DeathTimer.CorpseRemaining(val)));
					((Component)_waitText).gameObject.SetActive(false);
					return;
				}
				DiagnoseHeldCorpse(val);
			}
		}
		((Component)_waitText).gameObject.SetActive(false);
		((Component)_corpseWaitText).gameObject.SetActive(false);
	}

	private static void DiagnoseHeldCorpse(DeadPlayer held)
	{
		try
		{
			if (!((Object)(object)_diagCorpse == (Object)(object)held))
			{
				_diagCorpse = held;
				Player player = held.Player;
				CannibalFx cannibalFx = (((Object)(object)player != (Object)null) ? ((Component)player).GetComponent<CannibalFx>() : null);
				CorpseEconomy component = ((Component)held).GetComponent<CorpseEconomy>();
				string text = (((Object)(object)player == (Object)null) ? "owner null" : (((Object)(object)cannibalFx == (Object)null) ? "owner has no CannibalFx" : ((cannibalFx.DeathTime < 0f) ? string.Format("fx.deathTime not synced (-1); eco={0}", ((Object)(object)component != (Object)null) ? component.DeathTime.ToString("0.0") : "none") : $"fx.deathTime {cannibalFx.DeathTime:0.0} vs netTime {DeathTimer.NetworkTime():0.0}, wait {Config.ForcedWaitSeconds.Value}")));
				Plugin.LogWarn("[BetterCorpses] held corpse not in wait: " + text);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogWarn("DiagnoseHeldCorpse: " + ex.Message);
		}
	}
}
internal static class UiFonts
{
	private static Font _cjk;

	public static Font Cjk
	{
		get
		{
			if ((Object)(object)_cjk == (Object)null)
			{
				string[] array = new string[6] { "Microsoft YaHei", "SimHei", "Microsoft JhengHei", "Noto Sans CJK SC", "Noto Sans SC", "Arial" };
				foreach (string text in array)
				{
					try
					{
						Font val = Font.CreateDynamicFontFromOSFont(text, 24);
						if ((Object)(object)val != (Object)null)
						{
							_cjk = val;
							break;
						}
					}
					catch
					{
					}
				}
				if ((Object)(object)_cjk == (Object)null)
				{
					try
					{
						_cjk = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
					}
					catch
					{
					}
				}
				if ((Object)(object)_cjk == (Object)null)
				{
					try
					{
						_cjk = Resources.GetBuiltinResource<Font>("Arial.ttf");
					}
					catch
					{
					}
				}
			}
			return _cjk;
		}
	}
}